【问题标题】:Python: Excluding Modules PyinstallerPython:排除模块 Pyinstaller
【发布时间】:2011-06-20 21:10:19
【问题描述】:

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

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

我确实尝试过编辑 Pyinstaller 制作的规范文件。

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

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

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

【问题讨论】:

    标签: python pyinstaller


    【解决方案1】:

    自己寻找答案

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

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

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

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

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

    开始方式

    • 如下创建一个脚本文件(例如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 中查看比document 更多的细节

    最终,您可以使用任何 python 方式来设置您真正想要的 a.binariesa.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
    

    【讨论】:

      【解决方案2】:

      你可以试试这个,它比 .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}')
      

      希望你觉得这很有用!

      【讨论】:

        【解决方案3】:

        虽然可能已经给出了更好的解决方案,但还有一种方法: 您可以在 'pyinstaller' 命令中使用 '--exclude-module' 属性,但是当您必须排除许多模块时,此方法相当冗长。

        为了使工作更容易,您可以编写一个包含所有值得跳过的库的批处理脚本文件,然后一次又一次地使用它。

        类似这样的:

        @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安装的路径。

        【讨论】:

        • 这就是为什么建议为一个新项目创建一个新的virtualenv。昨晚我做了同样的事情(在找到这个主题之前),我的包大小从 800MB 减少到 150MB。
        【解决方案4】:

        只是在我使用它们时总结一下这里的选项。

        PyInstaller TOC's - 正如文档所说:

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

        换句话说,就是:

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

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

        • 对于 特定 文件/模块,使用差异 (-) 和交集 (+) 操作来修改 TOC。 *

        • 对于添加/删除文件/模块的列表,遍历目录并与模式匹配代码进行比较。

        (* 顺便说一句,要使差异起作用,您似乎必须显式转换为 TOC() 并注意,由于它只是唯一定义集合元素的名称,因此您只需要指定 - 因此('sqlite3', None, None)等)

        下面是一个说明性示例(取自 .spec 文件)——无论好坏——我删除了对 scipy、IPython 和 zmq 的所有引用;删除特定的 sqlite、tcl/tk 和 ssl .DLL;插入缺少的 opencv .DLL;最后删除除 matplotlib 之外的所有数据文件夹...

        当 .pyc 文件尝试加载预期的 .DLL 时,生成的 Pyinstaller .exe 是否可以正常工作是 moot:-/

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-09-13
            • 2020-07-16
            • 2013-05-28
            • 1970-01-01
            • 2023-01-05
            • 2022-11-10
            • 2017-11-28
            相关资源
            最近更新 更多