簡體   English   中英

cx_Freeze - 防止包含不需要的包

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM