cx_Freeze - Preventing including unneeded packages
The reason for the not working "excludes" command was that I forgot to include the build options into the setup. After adding the respective line into the code excluding works:
from cx_Freeze import setup, Executableimport 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 programssetup( 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 decreased the program size from 230MB to 120MB. Nevertheless, I did not find a nice way of excluding all unneeded packages. By trial and error (deleting the biggest files in the build folder test-wise) I figured out which classes I can exclude.
I tried whether the matplotlib backends cause the problem and finally figured out that this is not the case. Nontheless, if anybody needs code to exclude all modules of a certain name scheme in a particular folder except some special ones, he may adjust the following to 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 about more elegant solutions. Further ideas are still welcome. Nevertheless, I regard the problem as solved for me.
I was having a similar problem on a very simple PyQt4 Gui for a small database where the program was 58Mb for a small amount of code, the problem being that the entire PyQt4 folder was being included in the program.
The article here refers to using zip_include_packages in your options to exclude files or to compress them to reduce the file size.
I excluded the entire PyQt4 folder and then included the bits I needed as shown below and it reduced the whole package to 16Mb automatically
options = {'build_exe': { 'packages':packages, 'zip_include_packages':'PyQt4', 'includes':['PyQt4.QtCore','PyQt4.QtGui','sqlite3','sys','os'],},
Not sure it is the right way to do it but seems to have no negative impact on my program as of yet
This is how I optimized my executable to the minimum file size
from cx_Freeze import setup, Executableimport subprocessimport sysNAME = 'EXE NAME'VERSION = '1.0'PACKAGES = ['pygame', ('import_name', 'package_name')]# if names are same just have a string not a tupleinstalled_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)