Cx_freeze 8.1.0 is broken for Pyside6
I’m working on packaging up a Python app for different platforms and I’m using cx_freeze to build it. I’m using Pyside6 as my GUI library. I’ve been able to get the app working on my local machine but when I tried to package it up with the latest release of cxFreeze I run into a problem.
Here’s a snippet from my app pyproject.toml file:
[tool.cxfreeze]
executables = [
{script = "src/willow/app.py", base = "gui"}
]
[tool.cxfreeze.build_exe]
excludes = ["tkinter", "unittest"]
zip_include_packages = ["encodings", "PySide6", "shiboken6"]
And here’s what happens when I run the `build step:
$ uv run cxfreeze build_exe
running build_exe
patchelf --version returns: 'patchelf 0.17.2\n'
WARNING: zip_include_packages=PySide6 ignored.
Traceback (most recent call last):
File "/project/dir/.venv/bin/cxfreeze", line 10, in <module>
sys.exit(main())
^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/cli.py", line 269, in main
setup(
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/__init__.py", line 66, in setup
return setuptools.setup(**attrs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/setuptools/__init__.py", line 117, in setup
return distutils.core.setup(**attrs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/setuptools/_distutils/core.py", line 186, in setup
return run_commands(dist)
^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/setuptools/_distutils/core.py", line 202, in run_commands
dist.run_commands()
File "/project/dir/.venv/lib/python3.12/site-packages/setuptools/_distutils/dist.py", line 1002, in run_commands
self.run_command(cmd)
File "/project/dir/.venv/lib/python3.12/site-packages/setuptools/dist.py", line 1104, in run_command
super().run_command(command)
File "/project/dir/.venv/lib/python3.12/site-packages/setuptools/_distutils/dist.py", line 1021, in run_command
cmd_obj.run()
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/command/build_exe.py", line 321, in run
freezer.freeze()
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/freezer.py", line 768, in freeze
self._freeze_executable(executable)
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/freezer.py", line 324, in _freeze_executable
finder.include_file_as_module(exe.main_script, exe.main_module_name)
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 794, in include_file_as_module
module = self._load_module_from_file(name, path, deferred_imports)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 506, in _load_module_from_file
self._load_module_code(module, loader, deferred_imports)
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 479, in _load_module_code
self._scan_code(module, deferred_imports)
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 678, in _scan_code
imported_module = self._import_module(
^^^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 275, in _import_module
module = self._internal_import_module(name, deferred_imports)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 345, in _internal_import_module
parent_module = self._internal_import_module(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 362, in _internal_import_module
module = self._load_module(
^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 433, in _load_module
self._load_module_code(module, loader, deferred_imports)
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 472, in _load_module_code
module.hook(self)
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/hooks/_pyside6_/__init__.py", line 89, in load_pyside6
finder.include_file_as_module(qt_debug, "PySide6._cx_freeze_qt_debug")
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 794, in include_file_as_module
module = self._load_module_from_file(name, path, deferred_imports)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/project/dir/.venv/lib/python3.12/site-packages/cx_Freeze/finder.py", line 496, in _load_module_from_file
ext = filename.suffix
^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'suffix'
It took me a little while to track down what is happening here. It turns out that the pyside6 hook inside cxFreeze 8.1.0 is looking for a `debug.py` file to include in the zip file but at some point this file was renamed to `_debug.py` (visible in the repo here).
This problem is fixed in the latest development build of cxFreeze which you can install by running:
uv pip install --upgrade --extra-index-url https://test.pypi.org/simple/ cx_Freeze --pre --no-cache
Running the same command above now results in a success message. I’m sure this will be fixed in 8.2.0 but the workaround seems to do the trick for now.