Cx_Freeze - Prevent Inclusion of Unnecessary Packages

I encoded a tiny python program using PyQt4. Now I want to use cx_Freeze to create a standalone application. Everything works fine - cx_Freeze automatically includes all the necessary modules; Received exe works.

The only problem is that cx_Freeze contains many unnecessary modules offline. Although I use only QtCore and QtGui, modules such as sqlite3, QtNetwork, or QtScript are also included. Surprisingly, in the resulting folder, I also found the PyQt5 DLL. It seems to me that cx_Freeze uses all the PyQt packages that I installed. The result is a 200 MB program - although I wrote only a small script.

How can I prevent this behavior?

I use the following setup.py:

import sys from cx_Freeze import setup, Executable setup( name="MyProgram", version="0.1", description="MyDescription", executables=[Executable("MyProgram.py", base = "Win32GUI")], ) 

I tried to explicitly exclude some packages (although rather randomly exclude all unused Qt modules) by adding this code:

 build_exe_options = {"excludes": ["tkinter", "PyQt4.sqlite3", "PyQt4.QtOpenGL4", "PyQt4.QtSql"]} 

but the top modules were still in use. I also tried

 build_exe_options = {"excludes": ["tkinter", "PyQt4.sqlite3", "QtOpenGL4", "QtSql"]} 

with the same result.

In addition to the incomplete Qt packages, I also find unbuilt folders with names such as "imageformats", "tcl", and "tk". How can I include only the necessary files in order to leave the offline folder and the installer as little as possible?

I searched for this problem for hours, but found this thread that didn't help me.

I am running python 3.4.2 amd64 on Windows 8.

I am happy with every decision that gives me the desired result, "autonomous" with a reasonable size. I also tried pyqtdeploy, but ran into an error: Unknown module in QT (but this is another question).

Edit:

I use two modules. One of them is a GUI class created by uic, "MyProgramGUIPreset". This file has the following import commands:

 from PyQt4 import QtCore, QtGui from matplotlibwidget import MatplotlibWidget 

In the main module, I do the following imports:

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

Perhaps this helps to find out what the problem is.

+6
source share
1 answer

The reason for the "exclude" command that was not working was that I forgot to include the build parameters in it. After adding the appropriate line to the code, excluding the work:

 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))], ) 

This reduced the size of the program from 230 MB to 120 MB. However, I did not find a good way to eliminate all unnecessary packages. From trial versions and errors (by deleting the largest files in the test-wise build folder), I found out which classes I can exclude.

I tried to see if the matplotlib backend caused the problem and finally realized that it wasn’t. However, if someone needs a code to exclude all modules of a certain name scheme in a certain folder, except for some special ones, he can configure the following for his needs:

 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} 

I would be happy with more elegant solutions. Further ideas are still welcome. However, I see the problem as a solution for me.

+7
source

Source: https://habr.com/ru/post/979069/


All Articles