Python cx_冻结-防止包括不需要的包

Python cx_冻结-防止包括不需要的包,python,deployment,pyqt,cx-freeze,Python,Deployment,Pyqt,Cx Freeze,我使用PyQt4编写了一个小型python程序。现在,我想使用cx\u Freeze创建一个独立的应用程序。一切正常-cx_Freeze自动包含所有必要的模块;生成的exe有效 唯一的问题是cx_将大量不需要的模块冻结到单机版中。尽管我只使用QtCore和QtGui,但也包括sqlite3、QtNetwork或QtScript等模块。令人惊讶的是,我在结果文件夹中也找到了PyQt5 DLL。在我看来,cx_Freeze似乎使用了我安装的所有PyQt软件包。结果是一个200Mb的程序——尽管我只写

我使用PyQt4编写了一个小型python程序。现在,我想使用cx\u Freeze创建一个独立的应用程序。一切正常-cx_Freeze自动包含所有必要的模块;生成的exe有效

唯一的问题是cx_将大量不需要的模块冻结到单机版中。尽管我只使用QtCore和QtGui,但也包括sqlite3、QtNetwork或QtScript等模块。令人惊讶的是,我在结果文件夹中也找到了PyQt5 DLL。在我看来,cx_Freeze似乎使用了我安装的所有PyQt软件包。结果是一个200Mb的程序——尽管我只写了一个很小的脚本

我如何防止这种行为

我使用以下setup.py:

import sys
from cx_Freeze import setup, Executable

setup(
    name="MyProgram",
    version="0.1",
    description="MyDescription",
    executables=[Executable("MyProgram.py", base = "Win32GUI")],
)
我试图明确地排除一些包(尽管排除所有未使用的Qt模块非常麻烦),添加以下代码:

build_exe_options = {"excludes": ["tkinter", "PyQt4.sqlite3",
                              "PyQt4.QtOpenGL4", "PyQt4.QtSql"]}
但上层模块仍在使用。我也试过了

build_exe_options = {"excludes": ["tkinter", "PyQt4.sqlite3",
                              "QtOpenGL4", "QtSql"]}
同样的结果

除了nedless Qt软件包之外,我还发现了一些不需要的文件夹,它们的名称有“imageformats”、“tcl”和“tk”。如何仅包含所需的文件,以使独立文件夹和安装程序尽可能小

我在谷歌上搜索了几个小时,但只找到了对我没有帮助的问题

我正在windows 8上运行python 3.4.2 amd64

我很高兴每一个解决方案都能给我一个合理大小的“独立”结果。我也尝试了pyqtdeploy,但遇到了错误:QT中的未知模块(但这是另一个问题)

编辑: 我使用两个模块。一个是uic创建的GUI类,“MyProgramGUIPreset”。此文件中有以下导入命令:

from PyQt4 import QtCore, QtGui
from matplotlibwidget import MatplotlibWidget
在主模块中,我执行以下导入:

import MyProgramGUIPreset
import numpy as np
from PyQt4.QtGui import QApplication, QMainWindow, QMessageBox
import sys
from math import *

也许这有助于找出问题所在。

无法使用“排除”命令的原因是我忘了在设置中包含构建选项。在代码中添加相应行(不包括工程)后:

from cx_Freeze import setup, Executable
import sys

# exclude unneeded packages. More could be added. Has to be changed for
# other programs.
build_exe_options = {"excludes": ["tkinter", "PyQt4.QtSql", "sqlite3", 
                                  "scipy.lib.lapack.flapack",
                                  "PyQt4.QtNetwork",
                                  "PyQt4.QtScript",
                                  "numpy.core._dotblas", 
                                  "PyQt5"],
                     "optimize": 2}

# Information about the program and build command. Has to be adjusted for
# other programs
setup(
    name="MyProgram",                           # Name of the program
    version="0.1",                              # Version number
    description="MyDescription",                # Description
    options = {"build_exe": build_exe_options}, # <-- the missing line
    executables=[Executable("MyProgram.py",     # Executable python file
                            base = ("Win32GUI" if sys.platform == "win32" 
                            else None))],
)

我会很高兴有更优雅的解决方案。我们仍然欢迎进一步的想法。尽管如此,我认为这个问题已经解决了。

对于一个小型数据库,在一个非常简单的PyQt4 Gui上,我遇到了一个类似的问题,其中程序的代码量为58Mb,问题是整个PyQt4文件夹都包含在程序中

本文提到在选项中使用zip_include_包来排除文件或压缩文件以减小文件大小

我排除了整个PyQt4文件夹,然后包含了我需要的位,如下所示,它自动将整个包缩减到16Mb

options = {
'build_exe': {
    'packages':packages,
    'zip_include_packages':'PyQt4',
    'includes':['PyQt4.QtCore','PyQt4.QtGui','sqlite3','sys','os'],
},

不确定这样做是否正确,但到目前为止似乎对我的程序没有负面影响

这就是我如何将可执行文件优化到最小文件大小的方法

来自cx\u冻结导入设置,可执行
导入子流程
导入系统
名称='EXE名称'
版本='1.0'
PACKAGES=['pygame',('import\u name','package\u name')]
#如果名称相同,只需要一个字符串而不是元组
已安装的_程序包=子进程。检查_输出([sys.executable,'-m',pip',freeze'])。解码('utf-8')
已安装的\u程序包=已安装的\u程序包。拆分('\r\n')
排除已安装的_包中的pkg的{pkg.split('=')[0],如果pkg!=''}
排除。添加('tkinter')
对于包装中的包装:
如果类型(pkg)=str:EXCLUDES.remove(pkg)
else:EXCLUDES.remove(包[1])
可执行文件=[可执行文件('main.py',base='Win32GUI',icon='Resources/Jungle-gramb-icon.ico',targetName=NAME)]
设置(
name=name,
版本=版本,
description=f'{NAME}作者',
选项={'build_exe':{'packages':[pkg for pkg in packages if type(pkg)==str else pkg[0]],
'包含文件':['文件夹'],
“排除”:排除,
“优化”:2},
可执行文件=可执行文件)

一般来说,“排除”是告诉it您不需要东西的一种方式。我猜您的脚本使用的是类似matplotlib的东西,它有用于不同GUI的后端-cx_Freeze无法判断将使用哪一个,因此它尝试将它们全部包含在内。如果你能找出是什么模块导致了这个问题,那么排除这个模块,你也会省去很多其他模块。@ThomasK:谢谢你的建议!事实上,我正在使用matplotlibwidget。我试图排除它:
build_exe_options={“excludes”:[“tkinter”,“matplotlibwidget”]}
但没有改变。关于如何找出哪个模块导致问题,您有什么提示吗?我还想知道我是否正确使用了“排除”-命令。是否可以排除明确使用的模块?如果matplotlibwidget导致问题:我可以在不忽略该小部件的情况下解决问题吗?什么是合适的解决方案?您可能希望排除所有未使用的后端的
matplotlib.backends.backend\u foo
(即除Qt4之外的所有后端)。看起来您可能没有将build_exe_选项传递到安装程序中-请参见此处的示例:谢谢,@ThomasK!事实上,我忘了将
build\u exe\u选项
传递给setup方法。现在我添加了
options={“build\u exe”:build\u exe\u options},
并排除了这些选项。也就是说,我可以传递我想要排除的所有模块的列表。但我仍然想知道如何一次排除所有不需要的模块。我尝试了
build_exe_options={“excludes”:[“matplotlib.backends.backend_foo”]}
,但没有做任何事情。我正确理解你的建议了吗,托马斯K?或者我必须在我的代码中以不同的方式包含
matplotlib.backends.backend\u foo
?由于我的英语知识有限,我很肯定我误解了你的
backend\u foo
(尤其是“foo”一词)。是,我想排除除(!)
matplotlib.backends.backend\u qt4agg
之外的所有matplotlib后端。我如何在不列出所有26种可能性的情况下实现这一点?我可以使用正则表达式吗?排除<代码>
options = {
'build_exe': {
    'packages':packages,
    'zip_include_packages':'PyQt4',
    'includes':['PyQt4.QtCore','PyQt4.QtGui','sqlite3','sys','os'],
},