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 переносить двоичные файлы, которые нужны "магии"?

Воссоздать проблему

Для воссоздания проблемы можно сделать следующее:

  1. Скопируйте и вставьте этот код в ваш редактор. Сохраните его как файл с именем "test.py"

    import magic
    
    m=magic.MAGIC_NONE
    print(m)
    
  2. Загрузите "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
    
  3. Откройте командную строку в том же каталоге, что и файл "test.py", и используйте следующую команду для компиляции программы с помощью pyinstaller:

    > pyinstaller test.py
    
  4. После этого перейдите во вновь созданный каталог /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=[],

...
Другие вопросы по тегам