Этот ответ относится к следующим версиям:
pyinstaller 3.4
setuptools 41.0.1
ibm_db 3.0.1
ibm_db_sa 0.3.4
sqlalchemy 1.3.3
Здесь есть две отдельные проблемы.
Непосредственная проблема (ошибка ImportError) - сбой при загрузке ibm_db.dll
ImportError происходит из-за того, что pyinstaller не копирует внешние (не python) библиотеки в пакет, если вы явно не запросите это.
Опция pyinstaller --add-binary
дает обходной путь для этого ImportError, см. Пример ниже.
Если ваш скрипт python использует SQLAlchemy для доступа к Db2, то вы можете увидеть второй симптом во время выполнения послездание с pyinstaller.Признак времени выполнения: либо
"sqlalchemy.exc.NoSuchModuleError: Не удается загрузить плагин: sqlalchemy.dialects: ibm_db_sa"
или
"sqlalchemy.exc.NoSuchModuleError: Не удается загрузить плагин: sqlalchemy.dialects: db2.ibm_db"
(в зависимости от префикса для URL-адреса, данного для create_engine ())
Этот симптом sqlalchemy.exe.NoSuchModuleError не относится к Db2, но может влиять на другие базы данных при использовании через SQLAlchemy с диалектом external (Db2, teradata, Snowke, Presto,...).Базы данных, использующие внутренние диалекты SQLAlchemy, могут просто работать "из коробки".
Здесь есть один обходной путь, возможны и другие обходные пути.
Внешние диалекты SQLAlchemy используют pkg_resources entry_points, чтобы позволить SQLAlchemy использовать их, ноpyinstaller пока не может справиться с этим без вашей помощи.Такая информация точки входа является своего рода метаданными о модуле.
Этот обходной путь использует ловушки pyinstaller для сбора метаданных соответствующих модулей и сообщает pyinstaller каталог (или каталоги), которые содержат эти файлы ловушек.Для Db2 с SQLAlchemy необходимы три файла хуков, hook-ibm_db.py, hook-ibm_db_sa.py, hook-sqlalchemy.py
.Я решил поместить эти файлы ловушек в тот же каталог, что и скрипт Python моего исходного файла.
Содержимое каждого из этих файлов состоит из двух строк, а содержимое отличается только именем модуля, содержащегося в нем.Вот пример одного из файлов hook-sqlalchemy.py
(для двух других необходимых файлов просто замените имя модуля соответствующим образом):
from PyInstaller.utils.hooks import copy_metadata
datas = copy_metadata('sqlalchemy')
Чтобы добавить ibm_db.dll
через --add-binary method
, вы можетелибо используйте параметр командной строки для pyinstaller, либо отредактируйте файл спецификации.
Итак, для обоих обходных путей предположим, что ваш ibm_db.dll находится в этом каталоге:
%LOCALAPPDATA%\programs\python\python37\lib\site-packages\ibm_db_dlls
и вы создаете переменнуючтобы указать на это местоположение:
> set ibm_db_path=%LOCALAPPDATA%\programs\python\python37\lib\site-packages\ibm_db_dlls
Для командного файла MS-Windows (с использованием ^ в качестве символа продолжения строки) пример командной строки pyinstaller для обработки обоих упомянутых выше обходных путей:
pyinstaller -y ^
--additional-hooks-dir=. ^
--hidden-import ibm_db_sa.ibm_db ^
--hidden-import ibm_db_dbi ^
--hidden-import ibm_db ^
--add-binary %LOCALAPPDATA%\Programs\Python\Python37\Lib\site-packages\ibm_db_dlls\ibm_db.dll;.\ibm_db_dlls ^
your_script.py
Примечания:
Если ваш скрипт на python явно импортирует модули, вам не нужно указывать их через опции --hidden-import (купитьвам все еще нужны хуки).
Файл ibm_db.dll должен находиться в подкаталоге ibm_db_dlls вашего комплекта, что является причиной для указания этого места назначения в параметре --add-binary.
Если вы собираете для Linux / Unix вместо ^.используйте \ как символ продолжения строки как обычно.