Исполняемый файл PyQt5 падает с отсутствующей DLL - PullRequest
2 голосов
/ 11 апреля 2019

Моя проблема связана с исполняемым файлом pyqt5, который я создал с помощью pyinstaller. Единственная команда, которую я использую:

pyinstaller script.py

Я не очень разбираюсь в выходных сообщениях Pyinstaller. Поэтому я публикую этот вопрос на тот случай, если кто-то другой может помочь мне выяснить, что такое отсутствующие модули или файлы.

Вот копия всего вывода Compile:

Github - выход Pyinstaller

Вот копия ошибки, которая появляется .. это происходит за миллисекунду:

Missing DLLs

Любые комментарии или помощь приветствуются. Если вы думаете, что у вас есть возможное решение, пожалуйста, попробуйте ответить. Я уверен, что это стоит посмотреть. Надеюсь, это что-то простое и из-за моего отсутствия знаний.

Еще одно замечание: я импортирую / использую модуль ibm_db и модуль оболочки ibm_db_dbi .

Вот копия моего спецификационного файла:

# -*- mode: python -*-

block_cipher = None

added_files = [
                (r'C:\Python37\Lib\site-packages\ibm_db_dlls\ibm_db.dll', '.')
              ]

a = Analysis(['InheritMainWindow.py'],
             pathex=['c:\\Python37\\PDFMaker_v3\\Prototype',
                     'C:\\Python37\\Lib\\site-packages\\',
                     'C:\\Python37\\Lib\\site-packages\\sqlalchemy\\connectors\\',
                     'C:\\Python37\\Lib\\site-packages\\clidriver\\',
                     'C:\\Python37\\Lib\\site-packages\\ibm_db_dlls',
                     'C:\\Python37\\Lib\\site-packages\\ibm_db.py'],
             binaries=[('ibm_db.dll', 'ibm_db_dlls')],
             datas=[],
             hiddenimports=['ibm_db', 'ibm_db_dbi'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='InheritMainWindow',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )

a.binaries = [x for x in a.binaries if os.path.dirname(x[1]).find("IBM") < 0]
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='InheritMainWindow')

PS вы можете повторить проблему со следующим:

import ibm_db
print('hello!')

в командной строке:

pyinstaller hello.py

После выполнения exe-файла в папке dist вы получите ту же ошибку, что и выше.

Вот список вещей, которые я пытался решить:

1) Предоставление полного пути в двоичном виде, например:

binaries=[(r'C:\Python37\Lib\site-packages\ibm_db_dlls\ibm_db.dll', 'ibm_db_dlls')]

Это не имеет значения, сбой все еще происходит. И я уже видел, как папка ibm_db_dlls появилась в моей папке dist . Таким образом, двоичный файл добавляется, но его просто не видно.

2) С форума разработчиков ibm здесь: https://developer.ibm.com/answers/questions/448999/python-3-db2-windows-10-problems-and-script-compil/

В качестве предложенного решения использовалась опция --clean. Я попробовал эту опцию в 'hello.py', где он только импортирует пакет ibm_db и фактически работает как exe. Но это решение не работает в моем основном проекте.

Исправление: Это НЕ работает даже на простом примере hello.py.

Окончательное обновление: я предоставил решение ниже!

Ответы [ 2 ]

2 голосов
/ 15 апреля 2019

Итак, я решил проблему. И я ожидаю, что это должно помочь многим людям. Первая часть решения - список PATHEX. Мне пришлось обновить этот список, чтобы он указывал на все каталоги IBM моей системы:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['InheritMainWindow.py'],
             pathex=['c:\\Python37\\PDFMaker_v3',
                     'C:\\Python37\\Lib\\site-packages\\ibm_db_dlls',
                     'C:\\Program Files (x86)\\ibm\\gsk8\\lib', 
                     'C:\\Program Files (x86)\\ibm\\gsk8\\bin', 
                     'C:\\Program Files (x86)\\IBM Informix Client SDK\\bin', 
                     'C:\\Program Files (x86)\\IBM\\SQLLIB_01\\BIN', 
                     'C:\\Program Files (x86)\\IBM\\SQLLIB_01\\FUNCTION', 
                     'C:\\Program Files (x86)\\IBM\\SQLLIB_01\\BIN', 
                     'C:\\Program Files (x86)\\IBM\\SQLLIB_01\\FUNCTION', 
                     'C:\\Program Files (x86)\\ibm\\gsk8\\lib', 
                     'C:\\Program Files (x86)\\ibm\\gsk8\\bin', 
                     'C:\\Program Files (x86)\\IBM Informix Client SDK\\bin'],
             binaries=[(r'C:\Python37\Lib\site-packages\ibm_db_dlls\ibm_db.dll', 'ibm_db_dlls')],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='InheritMainWindow',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='InheritMainWindow')

Следующая часть ответа была действительно сложной для понимания. Его можно найти в файле imb_db.py:

import os

if 'clidriver' not in os.environ['PATH']:
    os.environ['PATH'] = os.environ['PATH'] + ";" + os.path.join(os.path.abspath(os.path.dirname(__file__)), 'clidriver', 'bin')  
def __bootstrap__():
   global __bootstrap__, __loader__, __file__
   import sys, pkg_resources, imp
   __file__ = pkg_resources.resource_filename(__name__,'ibm_db_dlls\\ibm_db.dll')
   __loader__ = None; del __bootstrap__, __loader__
   imp.load_dynamic(__name__,__file__)
__bootstrap__()

Мне пришлось обновить переменную пути, чтобы включить каталог clidriver:

C:\Python37\Lib\site-packages\clidriver\bin

Предполагается, что imb_db.py добавляет это к пути, но добавляет его в неправильном формате или каталоге. Так что следующая строка:

__file__ = pkg_resources.resource_filename(__name__,'ibm_db_dlls\\ibm_db.dll')

Завершает поиск файлов .dll. Поэтому после выполнения этих двух обновлений программа запускается и успешно подключается к удаленной базе данных DB2.

1 голос
/ 10 мая 2019

@ RockAndRoleCoder Спасибо за ваш вопрос и ответ. Я встречался с такой же ситуацией в Windows7 Python3.7 ibm-db 3.0.1
с вашей подсказкой , Я думаю, что причина в том, что exe не может найти * .dll в clidriver \ bin и ibm_db.dll, и решить его с помощью аналогичного метода в два этапа

Frist: так же, как вы, добавьте каталог clidriver в системный путь

**\site-packages\clidriver\bin

Второй pack с аргументом --add-binary

 Pyinstaller --add-binary **\Lib\site-packages\ibm_db_dlls\ibm_db.dll;.\ibm_db_dlls myproject.py

Тогда все нормально!

...