Search code examples
pythoncx-freeze

cx_Freeze common lib folder between executables


I'm compiling a suite of python scripts into executables. I'm using cx_Freeze in order to do so.

The rather common problem is that the lib folder becomes very large. I have excluded modules as much as possible to reduce the size of this but it is still quite sizeable.

Since I am compiling multiple executables, is it possible to have a single shared lib folder that gets referenced by them all to reduce disk size?

An example setup.py is as follows:

import sys, os
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
    base = 'Win32GUI'

executables = [
    Executable('MYSCRIPT.py', base=base)
]

additional_mods = ["numpy.core._methods", "numpy.lib.format"]
exclude_mods = ["babel", "scipy", "PyQt5", "tornado", "zmq", "sphinx", "sphinx_rtd_theme", "psutil", "notebook", "nbconvert", "lxml", "cryptography", "bottleneck", "matplotlib"]

build_exe_options = {"excludes": exclude_mods, "includes": additional_mods, "optimize": 1}

os.environ['TCL_LIBRARY'] = r'C:\ProgramData\Anaconda3\tcl\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\ProgramData\Anaconda3\tcl\tk8.6'

setup(name='MYSCRIPT',
      version='0.1',
      includes = ['os'],
      options = {"build_exe": build_exe_options},
      description='MYSCRIPT',
      executables=executables
      )

Solution

  • Yes it is possible. The trick is to use a single setup.py where the multiple scripts are added to the executables list.

    Take for example the following pair of console-based scripts which both use numpy:

    main1.py:

    import numpy
    
    print('Program 1, numpy version %s' % numpy.__version__)
    input('Press ENTER to quit')
    

    main2.py:

    import numpy
    
    print('Program 2, numpy version %s' % numpy.__version__)
    input('Press ENTER to quit')
    

    You can freeze this scripts at once with cx_Freeze using the following setup.py:

    from cx_Freeze import setup, Executable
    
    base = None
    
    executables = [Executable('main1.py', base=base),
                   Executable('main2.py', base=base)]
    
    additional_mods = ["numpy.core._methods", "numpy.lib.format"]
    
    build_exe_options = {"includes": additional_mods}
    
    setup(name='MYSCRIPTS',
          version='0.1',
          options={"build_exe": build_exe_options},
          description='MYSCRIPTS',
          executables=executables)
    

    You get then two executables main1.exe and main2.exe sharing the same lib folder containing numpy.