Pyinstaller - libmagic не найден после компиляции приложения
проблема
Я пишу приложение на Python. Он отлично работает в моей среде Python, но когда я компилирую его с помощью PyInstaller и пытаюсь запустить полученный исполняемый файл, я получаю следующую ошибку: ImportError: failed to find libmagic. Check your installation
У меня есть ощущение, что это как-то связано с "python-magic-bin", установкой, содержащей двоичные файлы, которые требовались для модуля с именем "magic", потому что если я удалю "python-magic-bin" из моей среды Python и попытаться запустить приложение, я получаю точно такую же ошибку. Я думаю, что по каким-то причинам эти двоичные файлы не переносятся в скомпилированный exe.
Если это имеет значение, я установил "python-magic-bin" из файла.whl. Эта установка добавила папку с именем "libmagic" файлы libmagic.dll и magic.mgc в каталог, в который был установлен "magic".
Вопрос
Если я прав насчет проблемы, как я могу заставить PyInstaller переносить двоичные файлы, которые нужны "магии"?
Воссоздать проблему
Для воссоздания проблемы можно сделать следующее:
Скопируйте и вставьте этот код в ваш редактор. Сохраните его как файл с именем "test.py"
import magic m=magic.MAGIC_NONE print(m)
Загрузите "python_magic_bin-0.4.14-py2.py3-none-win32.whl" по этой ссылке и используйте следующие команды в интерпретаторе, чтобы установить необходимые библиотеки для Python 3.6
>>> pip install pyinstaller >>> pip install python-magic >>> pip install python_magic_bin-0.4.14-py2.py3-none-win32.whl >>> pip install libmagic
Откройте командную строку в том же каталоге, что и файл "test.py", и используйте следующую команду для компиляции программы с помощью pyinstaller:
> pyinstaller test.py
После этого перейдите во вновь созданный каталог /dist/test (
cd ./dist/test
) и запустите.exe, используя:> ./test.exe
После запуска вы должны увидеть сообщение об ошибке: ImportError: failed to find libmagic. Check your installation
а также Failed to execute script test
Spec File
Это файл спецификации, который я использую для компиляции своего проекта.
# -*- mode: python -*-
block_cipher = None
a = Analysis(['main.py'],
pathex=['D:\\Home_Python\\pytags'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='main',
debug=False,
strip=False,
upx=True,
console=True )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='main')
Версии
Для этого проекта я использую:
- Python 3.6.3
- PyInstaller 3.3.1
- Libmagic 1.0
- Python-Magic 0.4.15
- Python-Magic-Bin 0.4.14
2 ответа
Я выяснил проблему через пару дней, так что я собираюсь документировать свое решение здесь для тех, кто может столкнуться с той же проблемой в будущем.
Вопрос заключается в методе, который libmagic
использует для поиска.dll-файла, он должен работать должным образом.
Направляйтесь к Lib/site-packages/magic
под вашей установкой Python и скопируйте файл с именем magic.py
и папка с именем libmagic
в каталог вашего проекта Python. После этого откройте magic.py
в вашей предпочтительной IDE. Если вы перейдете к строке 156, вы увидите этот фрагмент кода:
bin_dist_path = os.path.join(os.path.dirname(__file__), 'libmagic')
Это линия, которая вызывает нашу проблему. Он ищет папку с именем libmagic в том же каталоге, что и magic.py
файл. В частности, проблема здесь заключается в том, что __file__
переменная не работает так же, когда файл заморожен в файл.exe, поэтому я заменил __file__
с sys.executable
, Получившаяся строка выглядела так:
bin_dist_path = os.path.join(os.path.dirname(sys.executable), 'libmagic')
Сохраните файл, скомпилируйте вашу программу и скопируйте libmagic
папку в тот же каталог, что и полученный файл.exe.
Если вы запустите.exe, все должно работать правильно.
Если есть что-то, что я мог бы уточнить, или у вас есть вопросы, пожалуйста, не стесняйтесь спрашивать.
Не хотел помещать это в другой комментарий, потому что это было бы не так заметно...
Это работает для меня. Просто измените файл .spec, включив в него дополнительные файлы:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
extra_files = [('venv/Lib/site-packages/magic','magic')]
a = Analysis(['main.py'],
pathex=['D:\\Home_Python\\pytags'],
binaries=[],
datas=extra_files,
hiddenimports=[],
...