我已经开始在Py2Exe上使用Pyinstaller了。但是我很快就遇到了问题。如何排除我不想要的模块,以及如何查看包含在单个可执行文件中的模块?
我可以在Python安装中从DLL文件夹中删除一些pyd
和dll
文件,因此Pyinstaller找不到它们,因此不包含它们。我真的不想对所有模块这样做,因为它会变得非常艰巨。
我尝试编辑Pyinstaller制作的spec文件。
a.binaries - [('ssl','pydoc',)],
但是文件的大小保持不变,所以我得出的结论是没有用。
那么我如何才能看到Pyinstaller包含哪些模块以及如何排除那些我不想要的模块呢?
答案 0 :(得分:22)
在我使用它们时,只是总结一下这些选项。
PyInstaller TOC - 正如文档所说:
TOC似乎是表单元组的列表(名称,路径, 类型代码)。实际上,它是一个有序的集合,而不是列表。 TOC包含否 重复,其中唯一性仅基于名称。
换句话说,只需:
a_toc = [('uname1','/path/info','BINARY'),('uname2','/path/to','EXTENSION')...]
因此,在你的.spec文件中 - 一旦你得到了脚本的Analysis结果 - 你就可以通过以下任一方式进一步修改相应的TOC:
对于特定的文件/模块,使用差异( - )和交叉(+)操作来修改TOC。 *
用于添加/删除文件/模块的列表,迭代TOC并与模式匹配代码进行比较。
(*顺便说一句,为了使差异起作用,你似乎必须明确地转换为TOC()
并注意,因为它只是唯一定义集合元素的名称,所以你只需要指定 - 因此('sqlite3', None, None)
等。)
一个说明性示例(取自.spec文件)位于以下位置 - 无论好坏 - 我删除了对scipy,IPython和zmq的所有引用;删除特定的sqlite,tcl / tk和ssl .DLL;插入缺少的opencv .DLL;最后删除除matplotlib之外的所有数据文件夹...
当.pyc文件尝试加载预期的.DLL时,生成的Pyinstaller .exe是否会起作用是没有问题:-/
# Manually remove entire packages...
a.binaries = [x for x in a.binaries if not x[0].startswith("scipy")]
a.binaries = [x for x in a.binaries if not x[0].startswith("IPython")]
a.binaries = [x for x in a.binaries if not x[0].startswith("zmq")]
# Target remove specific ones...
a.binaries = a.binaries - TOC([
('sqlite3.dll', None, None),
('tcl85.dll', None, None),
('tk85.dll', None, None),
('_sqlite3', None, None),
('_ssl', None, None),
('_tkinter', None, None)])
# Add a single missing dll...
a.binaries = a.binaries + [
('opencv_ffmpeg245_64.dll', 'C:\\Python27\\opencv_ffmpeg245_64.dll', 'BINARY')]
# Delete everything bar matplotlib data...
a.datas = [x for x in a.datas if
os.path.dirname(x[1]).startswith("C:\\Python27\\Lib\\site-packages\\matplotlib")]
答案 1 :(得分:4)
您可以使用Python操作Analysis类生成的列表。请注意,这些是PyInstaller的TOC格式。
a = Analysis(...)
...
# exclude anything from the Windows system dir
a.binaries = [x for x in a.binaries if not
os.path.dirname(x[1]).startswith("C:\\Windows\\system32")]
答案 2 :(得分:1)
我已经看到很多类似的问题,但是没有人教您如何自己调试。
pyinstaller的文档可能对初学者有用,但是一旦您需要更多...
个人认为pyinstaller文档不友好(示例太少)并且缺少更新。
例如,document显示pyinstaller的版本为3.2。 (3.5现在可用(2019/10/5))
我想说的是,您应该从源代码中找到答案
# run_pyinstaller.py
from PyInstaller.__main__ import run
run()
在运行此脚本之前,您可以分配参数,例如“ -clean your.spec ”
在{env_path}/Lib/site-packages/PyInstaller/building/build_main.py -> def build(...) ... -> exec(code, spec_namespace)
处设置断点,如下所示:
注意:如果您不使用虚拟环境,则实际路径应为 {Python} /Lib/site-packages/PyInstaller/building/build_main.py
然后您可以查看您感兴趣的任何变量。
此外,您还将了解有关pyinstaller.exe实际执行操作的更多信息。
例如,您学习TOC的类是继承列表,并从PyInstaller.building.datastruct
中了解比document更多的细节。最终,您可以使用任何python方式来设置您真正想要的a.binaries
和a.datas
from PyInstaller.building.datastruct import TOC, Tree
from PyInstaller.building.build_main import Analysis
from PyInstaller.building.api import EXE, PYZ, COLLECT, PKG, MERGE
答案 3 :(得分:1)
你可以试试这个,它比 .bat 脚本好多了:
# Just add or remove values to this list based on the imports you don't want : )
excluded_modules = [
'numpy',
'jedi',
'PIL',
'psutil',
'tk',
'ipython',
'tcl',
'tcl8',
'tornado'
]
append_string = ''
for mod in excluded_modules:
append_string += f' --exclude-module {mod}'
# Run the shell command with all the exclude module parameters
os.system(f'pyinstaller myfile.py --noconfirm {append_string}')
希望你觉得这有用!
答案 4 :(得分:0)
尽管可能已经给出了更好的解决方案,但是还有另一种方法: 您可以将'--exclude-module'属性与'pyinstaller'命令一起使用,但是当您必须排除许多模块时,此方法相当冗长。
为了简化工作,您可以编写一个批处理脚本文件,其中包含所有值得跳过的库,并可以一次又一次地使用它。
类似这样的东西:
@echo off
pyinstaller --onefile a.py --exclude-module matplotlib ^
--exclude-module scipy ^
--exclude-module setuptools ^
--exclude-module hook ^
--exclude-module distutils ^
--exclude-module site ^
--exclude-module hooks ^
--exclude-module tornado ^
--exclude-module PIL ^
--exclude-module PyQt4 ^
--exclude-module PyQt5 ^
--exclude-module pydoc ^
--exclude-module pythoncom ^
--exclude-module pytz ^
--exclude-module pywintypes ^
--exclude-module sqlite3 ^
--exclude-module pyz ^
--exclude-module pandas ^
--exclude-module sklearn ^
--exclude-module scapy ^
--exclude-module scrapy ^
--exclude-module sympy ^
--exclude-module kivy ^
--exclude-module pyramid ^
--exclude-module opencv ^
--exclude-module tensorflow ^
--exclude-module pipenv ^
--exclude-module pattern ^
--exclude-module mechanize ^
--exclude-module beautifulsoup4 ^
--exclude-module requests ^
--exclude-module wxPython ^
--exclude-module pygi ^
--exclude-module pillow ^
--exclude-module pygame ^
--exclude-module pyglet ^
--exclude-module flask ^
--exclude-module django ^
--exclude-module pylint ^
--exclude-module pytube ^
--exclude-module odfpy ^
--exclude-module mccabe ^
--exclude-module pilkit ^
--exclude-module six ^
--exclude-module wrapt ^
--exclude-module astroid ^
--exclude-module isort
或者您始终可以使用新的python安装,只需在安装时更改新python安装的路径即可。