Python:排除模块 Pyinstaller

发布于 2024-10-16 01:36:27 字数 393 浏览 2 评论 0原文

我开始使用 Pyinstaller 而不是 Py2Exe。然而我很快就遇到了问题。如何排除不需要的模块,以及如何查看包含在单个可执行文件中的模块?

我可以从 Python 安装中的 DLL 文件夹中删除一些 pyddll 文件,这样 Pyinstaller 就找不到它们,因此不会包含它们。我真的不想对所有模块都这样做,因为这会变得相当困难。

我确实尝试编辑 Pyinstaller 生成的规范文件。

a.binaries - [('ssl','pydoc',)],

但文件的大小保持不变,所以我断定这不起作用。

那么我如何查看 Pyinstaller 包含哪些模块以及如何排除那些我不想要的模块?

I've begun using Pyinstaller over Py2Exe. However I've rather quickly run into a problem. How do I exclude modules that I don't want, and how do I view the ones that are getting included into the single executable file?

I can remove some pyd and dll files from the DLL folder in my Python installation so Pyinstaller doesn't find and therefore doesn't include them. I don't really want to be doing that with all the modules as it will get quite arduous.

I did try edit the spec file that Pyinstaller makes.

a.binaries - [('ssl','pydoc',)],

But the size of the file remained the same so I conclude that didn't work.

So how can I see what modules Pyinstaller are including and how do I exclude those that I do not want?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我还不会笑 2024-10-23 01:36:27

只是总结一下我使用的选项。

PyInstaller TOC - 正如文档所述:

目录似乎是以下形式的元组列表(名称、路径、
类型代码)。事实上,它是一个有序集,而不是一个列表。 TOC 不包含
重复项,其中唯一性仅基于名称。

换句话说,简单地说:

a_toc = [('uname1','/path/info','BINARY'),('uname2','/path/to','EXTENSION')...]

因此,在您的 .spec 文件中 - 一旦您获得了脚本的分析结果 - 您就可以通过以下任一方式进一步修改相应的目录:

  • 对于特定文件/模块使用差值 (-) 和交集 (+) 运算来修改 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...

exclude = ["scipy", "IPython", "zmq"]
a.binaries = [x for x in a.binaries if not x[0].startswith(tuple(exclude))]

# 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")]

Just to summarise the options here as I use them.

PyInstaller TOC's - are, as the documentation says:

A TOC appears to be a list of tuples of the form (name, path,
typecode). In fact, it's an ordered set, not a list. A TOC contains no
duplicates, where uniqueness is based on name only.

In otherwords, simply:

a_toc = [('uname1','/path/info','BINARY'),('uname2','/path/to','EXTENSION')...]

So, in your .spec file - once you've got the Analysis results of the script - you can then further modify the respective TOC's by either:

  • For specific files/modules use the difference (-) and intersection (+) operations to modify a TOC. *

  • For adding/removing lists of files/modules iterate over the the TOC and compare with pattern matching code.

(* As an aside, for the difference to work it seems you must explicitly cast to TOC() and note that since it is only the name that uniquely defines the element of the set, you only need to specify that - hence ('sqlite3', None, None) etc.)

An illustrative example (taken from a .spec file) is below where - for better or worse - I remove all references to scipy, IPython and zmq; delete specific sqlite, tcl/tk and ssl .DLL's; insert a missing opencv .DLL; and finally remove all data folders found apart from matplotlib ones...

Whether the resulting Pyinstaller .exe will then work when an .pyc file tries to load an expected .DLL is moot:-/

# Manually remove entire packages...

exclude = ["scipy", "IPython", "zmq"]
a.binaries = [x for x in a.binaries if not x[0].startswith(tuple(exclude))]

# 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")]
戏剧牡丹亭 2024-10-23 01:36:27

虽然可能已经给出了更好的解决方案,但还有一种方法:
您可以将“--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 安装的路径即可。

Although better solutions may have been given but there is one more method:
You can use the '--exclude-module' attribute with the 'pyinstaller' command but this method is quite lengthy when you have to exclude many modules.

To make the work easier, you can write a batch script file with all the libraries worth skipping and use it again and again.

Something like this:

@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

Or you can always use a new python installation, just change the path of the new python installation while installing.

烧了回忆取暖 2024-10-23 01:36:27

您可以尝试一下,它比 .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}')

希望您发现这很有用!

You can just try this, it's much better than a .bat script:

# 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}')

Hope you find this useful!

痴情换悲伤 2024-10-23 01:36:27

自己寻找答案

我见过很多这样的问题,但没有人教你如何自己调试。

pyinstaller 的文档可能对初学者有用,但是一旦您需要更多...

个人认为 pyinstaller 文档不友好(示例太少)并且缺乏更新。

例如,文档显示pyinstaller的版本是3.2。 (3.5现已推出(2019/10/5))现在(2020-12-15)它们都有相同的版本

我想说你应该从源代码中找到答案

START WAY

  • 创建一个脚本文件(例如 run_pyinstaller.py),如下所示:
# 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

在此处输入图像描述

  • 最后,您运行到此处并按单步执行按钮。您将进入 .spec 文件

,然后您可以观察您感兴趣的任何变量。

此​​外,您还将了解有关 pyinstaller.exe 实际做什么的更多信息。

例如,您学习 TOC 类继承到列表,并查看比 文档来自 PyInstaller.building.datastruct.py

在此处输入图像描述

最终,您可以使用任何 python 方式来设置 a.binaries 和 < code>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

FIND THE ANSWER BY YOURSELF

I've seen a lot of questions like this, but no one teaches you how to debug by yourself.

document of pyinstaller may have useful for beginner, but once you need more ...

personally, think the pyinstaller documentation is not friendly (Too few examples) and lacks updates.

for example, The document shows the version of the pyinstaller is 3.2. (3.5 is available now (2019/10/5)) Now (2020-12-15) they both have the same version

I want to say that you should find the answer from source code

START WAY

  • create a script file (for example, run_pyinstaller.py) as below:
# run_pyinstaller.py

from PyInstaller.__main__ import run
run()
  • before you run this script you can assign parameters, like "--clean your.spec"

  • set breakpoint at {env_path}/Lib/site-packages/PyInstaller/building/build_main.py -> def build(...) ... -> exec(code, spec_namespace) like below:

    note: If you are not using the virtual environment, the actual path should be {Python}/Lib/site-packages/PyInstaller/building/build_main.py

enter image description here

  • finally, you run here and press button of step into. you will into .spec file

then you can watch any variables that you interested in.

also, you will learn more about pyinstaller.exe actually do what.

for example, you learn the class of TOC is inherits to list, and see more the detail than the document from PyInstaller.building.datastruct.py

enter image description here

eventually, you can use any python way to set a.binaries and a.datas that is you really wanted

ASSOCIATED FILE LOCATION

from PyInstaller.building.datastruct import TOC, Tree
from PyInstaller.building.build_main import Analysis
from PyInstaller.building.api import EXE, PYZ, COLLECT, PKG, MERGE
巴黎夜雨 2024-10-23 01:36:27

您可以使用 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")]

You can manipulate the lists produced by the Analysis class using Python. Note that these are in PyInstaller's TOC format.

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")]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文