Pyinstaller 和 Pycrypto
我们最近在一个项目中添加了pycrypto库,但现在用pyinstaller打包后,软件无法运行。
我之前在使用pyinstaller时遇到过新库的问题,但这次的情况我实在解决不了。
当我尝试运行打包好的软件时,遇到的错误如下(抱歉我只是大概说一下,打包过程比较耗时)
最开始的错误是这样的:
No package Crypto.Cipher
于是我在我的.spec文件中把'Crypto'
加到了hiddenimports
里。然后我又遇到了:
No module named Cipher
接着我把'Crypto'
改成了'Crypto.Cipher'
,结果又出现了:
Crypto.Cipher has no attribute AES
然后我把'Crypto.Cipher'
改成了'Crypto.Cipher.AES'
,结果又是:
File "C:\Folder\made\by\pyinstaller\Crypto.Cipher.AES", line 49 in <module>
ImportError: cannot import name blockalgo
最后我把'Crypto.Cipher.AES'
改成了'Crypto.Cipher.AES.blockalgo'
,但错误依然没有改变。
我尝试了几种不同的配置,但打包脚本的输出总是显示类似的信息:
ERROR: Hidden import 'blockalgo' not found.
有没有人知道怎么才能正确导入,或者有什么技巧可以让pycrypto和pyinstaller配合得更好?
4 个回答
来自 这个链接 : 使用 pycryptodomex
替代 pycryptodome
。还有 @galgalesh 在提问下的评论提到,为什么 pycrypto 不应该再使用。
pip uninstall -y pycrypto
pip uninstall -y pycryptodome
pip install pycryptodomex
pycryptodomex
提供了一个清晰的 Cryptodome 模块来替代 Crypto。所以,在你的 .py 程序中,把 Crypto 替换成 Cryptodome:
from Cryptodome.PublicKey import RSA
我现在重新运行了 pyinstaller,结果正常。无需做任何特别的 hiddenimports 等等。在 dist 文件夹里,现在有一个清晰的 Crpytodome
文件夹,里面包含所有的 .pyd 文件。
改动?为什么不直接添加呢?把这些内容加到 hiddenimport
里就解决了这个问题: 'Crypto', 'Crypto.Cipher', 'Crypto.Cipher.AES', 'Crypto.Random',
这个回答:
来自 https://stackoverflow.com/a/48408950/4355695:使用 pycryptodomex 替代 pycryptodome。而 @galgalesh 在提问下的评论解释了为什么不应该再使用 pycrypto。
你可以用以下命令卸载旧的库:
pip uninstall -y pycrypto
pip uninstall -y pycryptodome
然后安装新的库:
pip install pycryptodomex
pycryptodomex 提供了一个清晰的 Cryptodome 模块来替代 Crypto。所以,在你的 .py 程序中,把 Crypto 替换成 Cryptodome:
from Cryptodome.PublicKey import RSA
我现在重新运行了 pyinstaller,结果很好。没有必要做任何特别的隐藏导入等。在 dist 文件夹里,现在有一个清晰的 Cryptodome 文件夹,里面放着所有的 .pyd 文件。
对我来说,运行得非常完美!
使用 pycryptodomex 替代 pycrypto,就能正常工作!
我觉得这是因为 Python 3.6 和 pycrypto 的重大更新导致的!然后它就不再支持 2.7.16 了!
你可以通过使用Python的详细导入标志来确认隐藏导入是否是问题所在。如果导入信息显示“找不到模块”,但warnproject.txt文件中没有相同模块的“没有名为...的模块”消息,那么问题就是隐藏导入。
隐藏导入是在分析阶段通过钩住模块(进行隐藏导入的那个模块)来处理的。具体步骤如下:
创建一个名为hook-module.py的文件(其中module是完整的Python名称,比如hook-xml.dom.py),并把它放在某个地方。记住这个地方,作为你的私有钩子目录。
在.spec文件中,将你的私有钩子目录作为hookspath参数传递给Analysis,这样就会被搜索到。例如:
a = Analysis(['myscript.py'], hookspath='/my/priv/hooks') 在大多数情况下,钩子模块只需要一行代码:
hiddenimports = ['module1', 'module2'] 当Analysis找到这个文件时,它会像显式导入module1和module2一样继续处理。
这个问题似乎相关,答案也可能对你有帮助。
最后,这个报告似乎包含了类似的问题。用户似乎通过更新到pyinstaller 2.1来解决了这个问题,所以如果你还没试过,可以考虑一下。