Pyinstaller - 编译应用程序后找不到 libmagic

Posted

技术标签:

【中文标题】Pyinstaller - 编译应用程序后找不到 libmagic【英文标题】:Pyinstaller - libmagic not found after compiling app 【发布时间】:2018-06-08 13:49:35 【问题描述】:

问题

我正在用 Python 编写一个应用程序。它在我的 python 环境中运行良好,但是当我使用 PyInstaller 编译它并尝试运行生成的可执行文件时,我收到以下错误:ImportError: failed to find libmagic. Check your installation

我感觉这与“python-magic-bin”有关,这是一个包含名为“magic”的模块所需的二进制文件的安装,因为如果我从我的 Python 环境并尝试运行该应用程序,我得到了同样的错误。我认为由于某种原因,这些二进制文件没有被带到已编译的 exe 中。

如果有什么不同,我从 .whl 文件中安装了“python-magic-bin”。此安装添加了一个名为“libmagic”的文件夹 libmagic.dll 和 magic.mgc 到安装“magic”的目录中。

问题

如果我对这个问题的看法是正确的,我如何让 PyInstaller 继承“魔法”所需的二进制文件?

重现问题

可以执行以下操作来重现问题:

    将此代码复制并粘贴到您的编辑器中。将其保存为一个名为 “测试.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 installationFailed to execute script test

规格文件

这是我用来编译我的项目的规范文件。

# -*- 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

【问题讨论】:

如果您创建Minimal, Complete, and Verifiable 示例,您将获得更多更好的答案。尤其要确保输入和预期数据是完整的(不是伪数据),并且可以轻松剪切并粘贴到编辑器中,以便测试建议的解决方案。 我真的很喜欢 OP 对问题的表述方式——我也在为同样的事情苦苦挣扎。我怀疑 pyinstaller 在 C:\Python27\Lib\site-packages\PyInstaller\hooks 中需要一些它没有的东西。 苏珊娜,其实我不久前就发现了这个问题。我现在不能发布它,但我会尽快回复这个帖子并提供解决方案。 我只在虚拟环境中安装了一个包,但我从 C:\python 上的根 pythn 安装中提取了 pyinstaller,但我遇到了类似的问题。在 pyInstaller 编译期间但在运行时没有给出错误。用 pip 安装了这个包,然后它就可以工作了 【参考方案1】:

几天后我发现了这个问题,所以我将在这里记录我的解决方案,以供将来可能遇到同样问题的任何人使用。

问题在于libmagic 用于查找正常工作所需的 .dll 文件的方法。

转到 Python 安装下的 Lib/site-packages/magic 并将名为 magic.py 的文件和名为 libmagic 的文件夹复制到 Python 项目的目录中。之后,在您首选的 IDE 中打开 magic.py。如果你转到第 156 行,你会看到这段代码:

bin_dist_path = os.path.join(os.path.dirname(__file__), 'libmagic')

这是导致我们问题的线路。它在与magic.py 文件相同的目录中查找名为 libmagic 的文件夹。具体来说,这里的问题是__file__ 变量在文件被冻结为 .exe 文件时无法正常工作,因此我将__file__ 替换为sys.executable。结果行如下所示:

bin_dist_path = os.path.join(os.path.dirname(sys.executable), 'libmagic')

保存文件,编译您的程序,并将libmagic 文件夹复制到与生成的 .exe 文件相同的目录中。

如果您运行 .exe,现在一切都应该正常运行。

如果有什么我可以澄清或您有任何疑问,请随时提问。

【讨论】:

我会注意到我还在 .spec 文件的 binaries= 部分复制了 libmagic.dll 和 magic.mgc。 如果不想手动复制 libmagic 文件夹,可以在 spec 文件中添加:extra_files += [('venv/Lib/site-packages/magic/libmagic','libmagic' )] 并将其用于“数据”。【参考方案2】:

不想把它放在另一个评论中,因为它不会那么明显......

这对我有用。只需更改 .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=[],

...

【讨论】:

以上是关于Pyinstaller - 编译应用程序后找不到 libmagic的主要内容,如果未能解决你的问题,请参考以下文章

编译成功后找不到openni2库

ldd 说编译成功完成后找不到库

Electron Atom - 编译后找不到模块“Node-Windows”

更新到 vs2017 15.2 后找不到 C 头文件

Pyinstaller 在 python 3.7 中不起作用(找不到模块“编码”)

将项目的 .NET 目标框架从 4.0 更改为 3.5 后找不到文件(或程序集)