marcelotduarte / cx_Freeze

cx_Freeze creates standalone executables from Python scripts, with the same performance, is cross-platform and should work on any platform that Python itself works on.
https://marcelotduarte.github.io/cx_Freeze/
Other
1.36k stars 220 forks source link

Cx Freeze when running exe, custom package in project throws import error #1840

Closed mai1x9 closed 1 year ago

mai1x9 commented 1 year ago

@marcelotduarte

Hi there, I am using Cx Freeze version 6.14.7, on Windows 10 Virtual machine (on Azure). After freezing the app, I get import error. My Project Structure,

Project
     core/
           .... all python files under core
     net/
       ......
     utils/
        __init__.py
       logger.py
       ....
     ui//

When running the exe file, I am getting,

ModuleNotFound: No Module named utils.

Refer to below screenshot:

Screenshot (6)

Theres __init__.py file inside all packages. Why am I getting this module not found error???

the exe file, imports the logger.py from utils package as

from utils.logger import err_logger

This is where cx freeze is throwing error.


NOTE; When I tried earlier with cx freeze 6,5,3, on my older machine on Windows 10, I have got no issues with the cx freeze and the executable is working properly without any errors. Moving to Azure virtual machine windows 10, with latest version is throwing me above error.

When downgrading cx freeze to 6.10 or 6.5.3(which was working earlier) I get below error,

Traceback (most recent call last):
  File "setup.py", line 3, in <module>
    from cx_Freeze import setup, Executable
  File "C:\Users\windows\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\__init__.py", line 3, in <module>
    from .dist import bdist_rpm, build, build_exe, install, install_exe, setup
  File "C:\Users\windows\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\dist.py", line 18, in <module>
    from .windist import bdist_msi
  File "C:\Users\windows\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\windist.py", line 1, in <module>
    import distutils.command.bdist_msi
ModuleNotFoundError: No module named 'distutils.command.bdist_msi'
mai1x9 commented 1 year ago

The setup.py file for reference,

import os
import shutil
from cx_Freeze import setup, Executable

# czfreeze
base = "Win32GUI"

# new packages = pygame, sqlite3
packages = [
    'os', 'filecmp', 'tkinter', 'scapy',
    'pydivert', 'winshell', 'PIL', 'requests'
]

exclude_packages = [
    'numpy', 'scipy', 'matplotlib', 'distutils', 'IPython', 'dbus', 'notebook',
    'zmq', 'tornado', 'ipykernel', 'ninja2', 'ipython_genutils', 'ninja',
    'jedi', 'jupyter_core', 'jupyter_client', 'Crypto', 'lib2to3', 'lxml',
    'apt', 'apport', 'mouseinfo', 'olefile', 'ptompttoolkit', 'pycparser',
    'pydoc_data', 'pyperclip', 'pyrect', 'pytweening', 'pyximport',
    'traitlets', 'pygetwindow', 'pygments', 'pygtkcompact', 'pymsgbox',
    'uinttest', 'wccwidth', 'wgiref', 'xmlrpc', 'curses'
]

zip_packages = [
    "asyncio", "certifi", "chardet", "collections", "concurrent", "ctypes",
    "email", "encodings", "html", "http", "idna", "json", "logging", "urllib",
    "urllib3", "xml", 'winreg', 'ctypes', 'zipfile', 'sqlite3'
]

setup(
    name="Agent",
    version="0.1.8",
    description="cx freeze exe example",  # will appear in notification.
    options={
        'build_exe': {
            'packages': packages,
            'include_files': ['utils/', 'core/', "ui/", "net/", 'version/', "svc/"],
            "zip_include_packages": zip_packages,
            "include_msvcr": True,
            "excludes": exclude_packages
        },
    },  # base = "Win32GUI"
    executables=[
        Executable(
            "example.py",
            base=base,  # comment when you need console for Testing purpose
            icon="software.ico"),
        # convert the traqezClient_core.py to exe
        Executable(
            "engine.py",
            base=base,  # comment when you need console for Testing purpose
            icon="software.ico"
         )
    ])
mai1x9 commented 1 year ago

@marcelotduarte I could figure out following things, but it is quite strange.

@marcelotduarte

Hi there, I am using Cx Freeze version 6.14.7, on Windows 10 Virtual machine (on Azure). After freezing the app, I get import error. My Project Structure,

Project
     core/
           .... all python files under core
     net/
       ......
     utils/
        __init__.py
       logger.py
       ....
     ui//

My all question now boils down to, I want to have only single copy of the packages utils, core, ui, .. so on... in exe.win-amd64-3.8 root folder only and do not want extra copies in exe.win-amd64-3.8/lib. How to do it? Deleting the copies in lib throws the error.

mai1x9 commented 1 year ago

My all question now boils down to, I want to have only single copy of the packages utils, core, ui, .. so on... in exe.win-amd64-3.8 root folder only and do not want extra copies in exe.win-amd64-3.8/lib. How to do it? Deleting the copies in lib throws the error.

I could find out solution by adding below code at the top of python files which are converted to exe files

import sys
import os
sys.path.append(os.path.dirname(__file__))

However can you please explain why it has worked earlier with cx freeze 6.5.3 but not with 6.14.7 ??? Also regarding the error (refer to below quote)

NOTE; When I tried earlier with cx freeze 6,5,3, on my older machine on Windows 10, I have got no issues with the cx freeze and the executable is working properly without any errors. Moving to Azure virtual machine windows 10, with latest version is throwing me above error.

When downgrading cx freeze to 6.10 or 6.5.3(which was working earlier) I get below error,

Traceback (most recent call last):
  File "setup.py", line 3, in <module>
    from cx_Freeze import setup, Executable
  File "C:\Users\windows\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\__init__.py", line 3, in <module>
    from .dist import bdist_rpm, build, build_exe, install, install_exe, setup
  File "C:\Users\windows\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\dist.py", line 18, in <module>
    from .windist import bdist_msi
  File "C:\Users\windows\AppData\Local\Programs\Python\Python38\lib\site-packages\cx_Freeze\windist.py", line 1, in <module>
    import distutils.command.bdist_msi
ModuleNotFoundError: No module named 'distutils.command.bdist_msi'
marcelotduarte commented 1 year ago

When downgrading cx freeze to 6.10 or 6.5.3(which was working earlier) I get below error,

When downgrade cx_Freeze, downgrade setuptools too. For 6.10, setuptools >= 46.4.0. This version can be used to test 6.5.3 and 6.10. Olders cx_Freeze depends on distutils, newers depend on setuptools and reimplemented (borrowed) bdist_msi for example.

My all question now boils down to, I want to have only single copy of the packages utils, core, ui, .. so on... in exe.win-amd64-3.8 root folder only and do not want extra copies in exe.win-amd64-3.8/lib. How to do it? Deleting the copies in lib throws the error.

The correct search for modules is in lib. All modules should be in lib or in lib/library.zip. If there are duplicates, the lib would be preserved. For .dll, if msvcr or python DLLs, they should be alongside the executable. Others can be in lib or inside the modules. As a example: _sqlite3.dll in lib alongside sqlite3.pyd (a module) in lib.

I recommend that you use cx_Freeze latest version and trying to create a sample that can reproduce the error, so I could solve the issues.

mai1x9 commented 1 year ago

The correct search for modules is in lib. All modules should be in lib or in lib/library.zip. If there are duplicates, the lib would be preserved.

Yes. since I deleted duplicates from lib, it has raised module not found error.

Adding current root directory to sys path fixed issue. So executable not just uses lib folder, it will look for any custom package in current directory of executable too.

I dont think this could be a issue to be addressed. it was more conceptual question and misunderstanding.

Thank you very much for the help.