【发布时间】:2015-02-01 13:58:45
【问题描述】:
我使用 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"]}
结果相同。
除了 nedless 的 Qt 包之外,我还发现了类似“imageformats”、“tcl”和“tk”等名称的 unnedless 文件夹。我怎样才能包含仅需要的文件,以使独立文件夹和安装程序尽可能小?
我用谷歌搜索了这个问题几个小时,但只找到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 *
也许这有助于找出问题所在。
【问题讨论】:
-
一般来说,“排除”是告诉它你不需要的方式。我猜你的脚本正在使用类似 matplotlib 的东西,它具有不同 GUI 的后端 - cx_Freeze 无法判断将使用哪一个,因此它会尝试将它们全部包含在内。如果你能找出是什么模块导致了问题,排除它也应该去掉很多其他模块。
-
@ThomasK:感谢您的建议!事实上,我正在使用 matplotlibwidget。我试图排除它:
build_exe_options = {"excludes": ["tkinter", "matplotlibwidget"]}但没有任何改变。您对我如何找出导致问题的模块有什么提示吗?我也想知道我是否正确使用了“排除”命令。是否有可能排除明确使用的模块?如果 matplotlibwidget 导致问题:我可以在不遗漏小部件的情况下解决问题吗?什么是合适的解决方案? -
您可能希望排除所有未使用的后端
matplotlib.backends.backend_foo(即除 Qt4 之外的所有后端)。看起来您可能没有将 build_exe_options 传递给 setup - 请参阅此处的示例:cx-freeze.readthedocs.org/en/latest/distutils.html -
谢谢你,@ThomasK!确实,我忘记将
build_exe_options传递给设置方法。现在我添加了options = {"build_exe": build_exe_options},并且排除工作正常。也就是说,我可以传递我想要排除的所有模块的列表。但我仍然想知道如何一次排除 all 不需要的模块。我试过build_exe_options = {"excludes": ["matplotlib.backends.backend_foo"]},它没有做任何事情。我是否正确理解了您的建议,Thomas K?还是我必须在我的代码中以不同的方式包含matplotlib.backends.backend_foo? -
由于我的英语知识有限,我很确定我误解了您的
backend_foo(尤其是“foo”这个词)。是的,我想排除除 (!)matplotlib.backends.backend_qt4agg之外的所有 matplotlib 后端。如果不列出所有 26 种可能性,我怎样才能做到这一点?我可以使用正则表达式吗?排除matplotlib.backends会使文件尽可能小。我试图排除上述内容,然后包括matplotlib.backends.backend_qt4agg但这给了我一个例外,即没有同名的模块...
标签: python deployment pyqt cx-freeze