我用PyQt4编写了一个很小的python程序。现在,我想使用cx_Freeze创建一个独立的应用程序。一切正常 - cx_Freeze自动包含所有必要的模块;结果exe工作。
唯一的问题是cx_Freeze将大量不需要的模块打包到独立模块中。即使我只使用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"]}
结果相同。
除了无用的Qt包之外,我还找到了名为“imageformats”,“tcl”和“tk”的不需要的文件夹。如何仅包含所需文件以使独立文件夹和安装程序尽可能小?
我用谷歌搜索了这个问题几个小时,但只找到this thread,这对我没有帮助。
我在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))],
)
这将程序大小从230MB减少到120MB。尽管如此,我没有找到排除所有不需要的软件包的好方法。通过反复试验(以测试方式删除构建文件夹中的最大文件),我找出了可以排除的类。
我试过matplotlib后端是否会导致问题,最后发现事实并非如此。尽管如此,如果有人需要代码来排除特定文件夹中除某些特殊文件夹之外的某个名称方案的所有模块,他可以根据自己的需要调整以下内容:
mplBackendsPath = os.path.join(os.path.split(sys.executable)[0],
"Lib/site-packages/matplotlib/backends/backend_*")
fileList = glob.glob(mplBackendsPath)
moduleList = []
for mod in fileList:
modules = os.path.splitext(os.path.basename(mod))[0]
if not module == "backend_qt4agg":
moduleList.append("matplotlib.backends." + modules)
build_exe_options = {"excludes": ["tkinter"] + moduleList, "optimize": 2}
我会很高兴更优雅的解决方案。仍然欢迎进一步的想法。不过,我认为这个问题已经解决了。
我在一个非常简单的PyQt4 Gui上遇到类似的问题,对于一个小型数据库,程序为58Mb,少量代码,问题是整个PyQt4文件夹被包含在程序中。
文章here指的是在您的选项中使用zip_include_packages来排除文件或压缩它们以减小文件大小。
我排除了整个PyQt4文件夹,然后包含我需要的位,如下所示,它将整个包减少到16Mb
options = {
'build_exe': {
'packages':packages,
'zip_include_packages':'PyQt4',
'includes':['PyQt4.QtCore','PyQt4.QtGui','sqlite3','sys','os'],
},
不确定这是否正确,但似乎对我的计划没有负面影响