[英]cx_Freeze - Preventing including unneeded packages
我使用 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”的未定義文件夾。 如何僅包含所需的文件以使獨立文件夾和安裝程序盡可能小?
我用谷歌搜索了這個問題幾個小時,但只找到了這個對我沒有幫助的線程。
我在 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 文件夾都包含在程序中。
這里的文章是指在您的選項中使用 zip_include_packages 來排除文件或壓縮它們以減小文件大小。
我排除了整個 PyQt4 文件夾,然后包含了我需要的位,如下所示,它自動將整個包減少到 16Mb
options = {
'build_exe': {
'packages':packages,
'zip_include_packages':'PyQt4',
'includes':['PyQt4.QtCore','PyQt4.QtGui','sqlite3','sys','os'],
},
不確定這是正確的方法,但到目前為止似乎對我的程序沒有負面影響
這就是我將可執行文件優化為最小文件大小的方法
from cx_Freeze import setup, Executable
import subprocess
import sys
NAME = 'EXE NAME'
VERSION = '1.0'
PACKAGES = ['pygame', ('import_name', 'package_name')]
# if names are same just have a string not a tuple
installed_packages = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze']).decode('utf-8')
installed_packages = installed_packages.split('\r\n')
EXCLUDES = {pkg.split('==')[0] for pkg in installed_packages if pkg != ''}
EXCLUDES.add('tkinter')
for pkg in PACKAGES:
if type(pkg) == str: EXCLUDES.remove(pkg)
else: EXCLUDES.remove(pkg[1])
executables = [Executable('main.py', base='Win32GUI', icon='Resources/Jungle Climb Icon.ico', targetName=NAME)]
setup(
name=NAME,
version=VERSION,
description=f'{NAME} Copyright 2019 AUTHOR',
options={'build_exe': {'packages': [pkg for pkg in PACKAGES if type(pkg) == str else pkg[0]],
'include_files': ['FOLDER'],
'excludes': EXCLUDES,
'optimize': 2}},
executables=executables)
您需要創建一個列表來掃描 python 中的所有包,然后刪除列表中正在使用的包,最后為該列表分配 excludes 選項:(setup.py)
APP_NAME = "Hezzo"; ## < Your App's name
Python_File = "app.py"; ## < Main Python file to run
Icon_Path = "./icon.ico"; ## < Icon
Import = ["tkinter"]; ## < Your Imported modules (cv2,numpy,PIL,...)
################################### CX_FREEZE IGNITER ###################################
import sys, pkgutil;
from cx_Freeze import setup, Executable;
BasicPackages=["collections","encodings","importlib"] + Import;
def AllPackage(): return [i.name for i in list(pkgutil.iter_modules()) if i.ispkg]; # Return name of all package
def notFound(A,v): # Check if v outside A
try: A.index(v); return False;
except: return True;
build_exe_options = {
"includes": BasicPackages,
"excludes": [i for i in AllPackage() if notFound(BasicPackages,i)],
}
setup( name = APP_NAME,
options = {"build_exe": build_exe_options},
executables = [Executable(Python_File, base='Win32GUI', icon=Icon_Path, targetName=APP_NAME)]
);
示例 app.py:
import tkinter as tk;
windowTk = tk.Tk();
windowTk.mainloop();
在某些情況下,例如創建輕量級便攜式應用程序,您可以在導出后刪除 lib 文件夾中的額外 tcl 模塊文件和齒輪。 它有助於減少更多的兆字節(我的應用程序從 200MB 減少到 16MB 然后 10MB)。
並且您可以使用 WinRAR 創建可移植程序(帶有選項的 SFX 存檔)。 它通常減少 45% 以上。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.