Cx freeze workarounds

From wikinotes

six

six missing attributes

setup.py

def build_options():
    options = {
        # executable options
        'build_exe': {
            'packages': [
                'pkg_resources',
                'packaging',
                'setuptools',
                'six',
            ],
        }
    }

    # add six dependencies
    for module in dir(six.moves):
        if module[:2] != '__':
            # six.moves has attributes for both py2/3 only
            # modules. We need to suss out which this interpreter needs.
            try:
                importlib.import_module(module)
                options['build_exe']['packages'].append(module)
            except(ImportError):
                # in python3x six imports submodules as:
                # 'html_parser' instead of 'html.parser'
                try:
                    module = module.replace('_', '.')
                    importlib.import_module(module)
                    options['build_exe']['packages'].append(module)
                except(ImportError):
                    pass

    return options

if __name__ == '__main__':
    cx_Freeze.setup(..., options=build_options(), ...)

pyyaml

ImportError on build

cx_Freeze does not play nice with .egg python distributions. Delete pyyaml from your site-packages and reinstall as an sdist.

NOTE:

You can prevent python from ever installing egg distributions by creating a ~/.distutils.cfg file containing:

[easy_install]
zip_ok = False

mock

ImportError on build

Mock requires pbr to obtain it's version info. This is not compatible with cx_Freeze.

I do not have a generalized workaround for any pbr package, but if you build using python3 use unittest.mock instead of mock.

Qt

NOTE:

When using Qt.py with cx_Freeze, I have noticed that Qt.py does not get included in the executable's libs (leaving PySide, PySide2, in it's place). This is completely normal, and likely not your issue.

qt.qpa.plugin: Could not find the Qt platform plugin "windows" in ""

If your frozen application cannot start a ``QApplication`` , citing the above there are two possible issues:


1. The executable under a path that is a symlink/hardlink/directory-junction to a network-path. (symlinks work to local paths, just not UNC paths). Resolve by:

  • running it directly from the UNC path (instead of symlink)
  • copy it to a non UNC path then run it
  • specify a qt.conf (See #2)


2. If the above does not solve, you will need to inform Qt where to find it's plugins. You can do this using a ``qt.conf`` file, or using environment variables.

  • set envvar ``QT_PLUGINS_PATH={path-to-sitepackages}/PySide2/plugins``
  • in same directory as executable, create the file ``qt.conf`` .
[paths]
Plugins = C:/Python36/Libs/site-packages/PySide2/plugins

NOTE:

the paths referenced by Qt environment-variables or qt.conf may be symlinks to local files, or network-paths. They **cannot** be *symlinks to network-paths*

NOTE:

qt.conf paths must forward-slashes exclusively (even on windows).


multiprocessing

multiprocessing (unrecognized arguments: --multiprocessing-fork)

If your frozen application uses of the multiprocessing module, starting processes will not work.

You'll need to add the following code to the script being built into an executable (not setup.py) .

import multiprocessing
# .. your module code ...
if __name__ == '__main__':
    multiprocessing.freeze_support()

Windows does not have the syscall fork (which detaches a subprocess from it's parent, assigning it it's own PID). When running python scripts from a python interpreter, python simulates this by calling the python-executable ( sys.executable ) with it's commandline argument --multiprocessing-fork parent_pid=8856 pipe_handle=1316.

When you freeze a python script sys.executable becomes /path/to/your-application.exe , where you probably do not have the command-line flag --multiprocessing-fork defined. multiprocessing.freeze_support does some magic to start separate processes in a different way.