【问题标题】:Pyinstaller excluding SubModules while CompilingPyinstaller 在编译时排除 SubModules
【发布时间】:2020-06-02 03:11:04
【问题描述】:

我已经使用 PyQt5 开发了 UI,现在我正在使用 Pyinstaller 将代码转换为独立的应用程序,但问题是文件大小越来越大(接近 250MB)。我可以减小文件的大小,但不包括不必要的 PyQt5 导入。 关注我使用过的库 -

from PyQt5 import QtCore, QtGui, QtWidgets
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
import os,sys
from mat4py import loadmat
from matplotlib import pyplot as plt

PyQt5 库有以下许多子模块(QtCore、QtGui、QtWidgets、QtMultimedia、QtBluetooth、QtNetwork、QtPositioning、Enginio、QtWebSockets、QtWebKit、QtWebKitWidgets、QtXml、QtSvg、QtSql、QtTest),其中我只使用 QtCore、QtGui和 QtWidgets。

同样,我在其中使用 pyplot 的库 matplotlib 许多模块。

我想跳过程序不使用的模块,以便减小可执行文件的大小。

我的pyinstaller规范文件-

import sys
sys.setrecursionlimit(3000)

block_cipher = None

a = Analysis(['ReadMAT.py'],
             pathex=['C:\\Users\\Sekhar\\Documents\\PythonScripts\\RXP\\ReadMAT'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='ReadMAT',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=False, icon='ReadMAT.ico')

如何跳过不会进入编译过程的子模块。如何减小可执行文件的大小?

【问题讨论】:

    标签: python matplotlib pyqt5 pyinstaller


    【解决方案1】:

    PyInstaller 对每个包都有一个hook 机制,它处理包所需的二进制文件。

    对于像 Qt 这样的一些知名库,它实现了一个高效的钩子文件,只检索必要的二进制文件。但是如果您想排除某些部分,您需要自己通过排除命令或操作挂钩文件来完成:

    1. 通过使用--exclude-module 排除不必要的模块。通常,这就足够了。

    2. 通过修改特定的钩子文件并删除不需要的二进制文件。

      例如,在 Qt 的挂钩文件 (<Pyinstaller_path>/utils/hooks/qt.py) 中,有一个名为 _qt_dynamic_dependencies_dict 的变量,其中包含位于 <qt_installation_path>/Qt/bin 中的所有二进制文件,因此您可以删除每个不需要的文件。

      稍后在一个名为 get_qt_binaries 的函数中捆绑了其他 Qt 二进制文件,您可以像 opengl32sw.dll 一样删除不需要的每个。

    例如:

    _qt_dynamic_dependencies_dict = {
        ## "lib_name":              (.hiddenimports,           translations_base,  zero or more plugins...)
        # I've removed qt5bluetooth with commenting below line
        #"qt5bluetooth":             (".QtBluetooth",           None,               ),  # noqa: E241,E202
        "qt5concurrent":            (None,                     "qtbase",           ),
        ...
    }
    ...
    
    def get_qt_binaries(qt_library_info):
        binaries = []
        angle_files = ['libEGL.dll', 'libGLESv2.dll', 'd3dcompiler_??.dll']
        binaries += find_all_or_none(angle_files, 3, qt_library_info)
    
        # comment the following two lines to exclude the `opengl32sw.dll`
        # opengl_software_renderer = ['opengl32sw.dll']
        # binaries += find_all_or_none(opengl_software_renderer, 1, qt_library_info)
    
        # Include ICU files, if they exist.
        # See the "Deployment approach" section in ``PyInstaller/utils/hooks/qt.py``.
        icu_files = ['icudt??.dll', 'icuin??.dll', 'icuuc??.dll']
        binaries += find_all_or_none(icu_files, 3, qt_library_info)
    
        return binaries
    

    【讨论】:

    • 谢谢,但是 matplotlib 库也有这个钩子,因为当我在 util/hooks 文件夹中搜索时,我只能找到 qt.py 文件
    • @ChandraSekharK Matplotlib 有一个名为 hook-matplotlib.py 的钩子文件,但它不像 Qt,因为没有简单的二进制文件。请记住,我只是给您举了一个示例,但您不能将这种方式应用于所有包,您需要自己尝试并检查它是否损坏。
    猜你喜欢
    • 2014-07-02
    • 2016-06-07
    • 2018-12-22
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    相关资源
    最近更新 更多