A distutils extension to create standalone Windows programs from Python code

Overview

py2exe for Python 3

py2exe is a distutils extension which allows to build standalone Windows executable programs (32-bit and 64-bit) from Python scripts. Python versions included in the official development cycle are supported (from 3.6 to 3.9 included). py2exe can build console executables and windows (GUI) executables. Building windows services, and DLL/EXE COM servers might work but it is not actively supported.

Development of py2exeis hosted here: https://github.com/py2exe/py2exe.

Changes

Detailed changelog is published on GitHub.

Version 0.10.2.0:

  • New module finder with support for implicit namespace packages (PEP 420).
  • DLLFinder automatically excludes VC++ redist and Windows CRT DLLs from bundles.
  • Several fixes for bundling software with bundle_files<=2 (only the standard library is supported, other dependencies may or may not work).
  • New hooks for pycryptodome and shapely.

Version 0.10.1.0:

  • Add support for Python 3.9.
  • Drop support for Python 3.5.
  • New hooks for urllib3 and pandas.

Version 0.10.0.2 (from versions 0.9.x):

  • Introduce compatibility with Python 3.5, 3.6, 3.7, and 3.8.
  • Drop compatibility with Python 3.4 and earlier.
  • New or updated hooks for certifi, numpy, tkinter, socket, ssl, and six.
  • build_exe: the zipfile=None option has been removed.
  • runtime: the Python interpreter DLL is no longer altered before being inserted in the executable bundle.
  • Several bugfixes, better error messages.

Installation

pip install py2exe

Using a setup-script

Documentation about the setup-script and other usage tips are in the wiki pages at http://www.py2exe.org.

Using the builder

The build_exe CLI is not actively supported at the moment. Users are encouraged to create their own setup.py files. Documentation on how to use the CLI can be found here.

Known issues

  • The option bundle_files=0 is incompatible with ssl.
  • Building isapi extensions is not supported.
  • High-level methods or hooks to embed Qt plugins in the bundle (needed by PySide2/PyQt5) are missing.

Credits

Further informations about the original development of py2exe and other usage guidelines can be found in the original README.

Comments
  • Deprecation of `distutils` - slated for Python 3.12

    Deprecation of `distutils` - slated for Python 3.12

    I've been noticing this... probably since I first started using Python 3.10:

    0$ python setup.py py2exe
    C:\Users\Athan\Documents\Devel\infi-systray_py2exe\setup.py:1: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
      from distutils.core import setup
    running py2exe
    

    Do you have any plans for migrating py2exe itself away from using distutils ?

    I have a vague memory of you deprecating use of build_exe.exe, but even if that's correct then it's still installed along with py2exe and will output a setup.py that uses distutils:

    Athan@emilia MINGW64 ~/Documents/Devel/infi-systray_py2exe (main)
    0$ build_exe.exe -W setup-build_exe.py sample_systray.py
    Created setup-build_exe.py.
    Athan@emilia MINGW64 ~/Documents/Devel/infi-systray_py2exe (main)
    0$ head setup-build_exe.py
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    # Created by: python.exe -m py2exe -W setup-build_exe.py sample_systray.py
    
    from distutils.core import setup
    ...
    

    Obivously there's currently plenty of time. Python 3.12 will likely be available around October 2023, so still 19 months to go yet. But it would still be better to address this sooner rather than later.

    question 
    opened by Athanasius 44
  • Build/runtime error with infi.systray

    Build/runtime error with infi.systray

    We've been trying to get Windows system tray icon support into our project using infi.systray. It works, but we're having trouble getting py2exe to package it properly.

    Our issue is https://github.com/EDCD/EDMarketConnector/issues/1020

    I've made an example code repo at https://github.com/Athanasius/infi-systray_py2exe

    The main branch of that tries to do the bare minimum and gets the error as shown in https://github.com/Athanasius/infi-systray_py2exe/blob/main/sample_systray-bare-setup.log

    The setup-pkg_resources branch then attempts to include pkg_resources but gets the error as shown in https://github.com/Athanasius/infi-systray_py2exe/blob/setup-pkg_resources/sample_systray-with-pkg_resources.log

    Adding 'packages' to py2exe packages option gets us a little further... but then can't import other things. This is where I realised that pkg_resources includes a copy of packages in pkg_resources._vendor, but:

    1. That isn't recognised by py2exe as a package (__path__ is missing?)
    2. Doesn't work if included as a module instead.

    I realise this whole thing is because pkg_resources and packages are doing their own module importing directly, which makes it tricky for py2exe to find the correct files to include in the build.

    unable to reproduce 
    opened by Athanasius 25
  • SystemError building with pyproj

    SystemError building with pyproj

    Picking up on discussion from #18, I was able to get a few packages to work by specifying the package names in the options, but one it did not work for is pyproj.

    On Python 3.7.x (32 and 64-bit), same setup as in #18, but with pip install pyproj==2.2.2 to get a windows wheel. The following is the output of the resulting exe, with a bonus warning about distutils which I don't know is related. The last import, pyproj._crs is a pyc in the zip that loads a pyd outside the zip.

    ...\py2exe_zipimport_bug\dist\library.zip\distutils\__init__.py:15: UserWarning: The virtualenv distutils package at %s appears to be in the same location as the system distutils?
    Traceback (most recent call last):
      File "foo.py", line 1, in <module>
      File "<frozen importlib._bootstrap>", line 983, in _find_and_load
      File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 668, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 638, in _load_backward_compatible
      File "C:\Users\nick\.virtualenvs\tmp-b1da4736-4c9a-4313-808c-4bdae17f2fdb\lib\site-packages\pyproj\__init__.py", line 77, in <module>
        from pyproj.crs import CRS  # noqa: F401
      File "<frozen importlib._bootstrap>", line 983, in _find_and_load
      File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 668, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 638, in _load_backward_compatible
      File "C:\Users\nick\.virtualenvs\tmp-b1da4736-4c9a-4313-808c-4bdae17f2fdb\lib\site-packages\pyproj\crs.py", line 36, in <module>
        from pyproj._crs import CoordinateOperation  # noqa
      File "<frozen importlib._bootstrap>", line 983, in _find_and_load
      File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 668, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 638, in _load_backward_compatible
    SystemError: <method 'load_module' of 'zipimport.zipimporter' objects> returned NULL without setting an error
    
    opened by nchidsey 20
  • Add hook for _ssl

    Add hook for _ssl

    In python 3.7 and up, _ssl.pyd relies on libcrypto and libssl. These aren't picked up by py2exe, which is problematic for NVDA (see https://github.com/nvaccess/nvda/issues/9831)

    This patch is based on https://github.com/anthony-tuininga/cx_Freeze/pull/470 by @sekrause. I made sure that after building an NVDA distribution with this patch applied, the libcrypto and libssl modules were copied successfully.

    opened by leonardder 20
  • Impossible to freeze packages with a particular layout since py2exe 0.10.2.0

    Impossible to freeze packages with a particular layout since py2exe 0.10.2.0

    Originally reported as https://github.com/nvaccess/nvda/issues/12357 as this issue stops us from upgrading to post 0.10.1.0 versions of py2exe.

    To reproduce try to freeze py2exesample.zip with version 0.10.1.0 and then with any later versions including the latest 0.10.4.1. While with 10.1.0 the freezing process works as it should all later versions provide the following error:

    running py2exe
    Traceback (most recent call last):
      File "setup.py", line 5, in <module>
        data_files=[('.', ['data.txt'])]
      File "C:\Python37\lib\distutils\core.py", line 148, in setup
        dist.run_commands()
      File "C:\Python37\lib\distutils\dist.py", line 966, in run_commands
        self.run_command(cmd)
      File "C:\Python37\lib\distutils\dist.py", line 985, in run_command
        cmd_obj.run()
      File "D:\py2exesample\testing\lib\site-packages\py2exe\distutils_buildexe.py", line 192, in run
        self._run()
      File "D:\py2exesample\testing\lib\site-packages\py2exe\distutils_buildexe.py", line 272, in _run
        builder.analyze()
      File "D:\py2exesample\testing\lib\site-packages\py2exe\runtime.py", line 177, in analyze
        target.analyze(mf)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\runtime.py", line 78, in analyze
        modulefinder.run_script(self.script)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 62, in run_script
        self._scan_code(mod.__code__, mod)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 386, in _scan_code
        self.safe_import_hook(name, mod, fromlist, level)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 122, in safe_import_hook
        self.import_hook(name, caller, fromlist, level)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 104, in import_hook
        module = self._gcd_import(name)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 258, in _gcd_import
        return self._find_and_load(name)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 348, in _find_and_load
        self._scan_code(module.__code__, module)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 386, in _scan_code
        self.safe_import_hook(name, mod, fromlist, level)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 122, in safe_import_hook
        self.import_hook(name, caller, fromlist, level)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 107, in import_hook
        module = self._gcd_import(name, package, level)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 258, in _gcd_import
        return self._find_and_load(name)
      File "D:\py2exesample\testing\lib\site-packages\py2exe\mf34.py", line 303, in _find_and_load
        spec = importlib.util.find_spec(name, path)
      File "C:\Python37\lib\importlib\util.py", line 94, in find_spec
        parent = __import__(parent_name, fromlist=['__path__'])
      File "D:\py2exesample\samplePKG\__init__.py", line 1, in <module>
        import printData
      File "D:\py2exesample\printData.py", line 3, in <module>
        DATA_PATH = os.path.join(globalVars.appPath, globalVars.DATA_FILE_NAME)
    AttributeError: module 'globalVars' has no attribute 'appPath'
    
    

    Obviously the reproducer attached above is extremely silly and it would be easy to rewrite it, but as mentioned above we follow similar pattern in NVDA and it would be pretty difficult to modify its code so that this bug is not triggered. As soon as the line from .functions import my_avesome_func in samplePKG\__init__.py is commented out the program can be frozen successfully.

    bug 
    opened by lukaszgo1 14
  • pandas or matplotlib get

    pandas or matplotlib get "attempted relative import beyond top-level package" error

    hello, i am a new programmer. i want to write a tools then share it with others。 the python version is: Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Intel)] on win32 py2exe version is: 0.9.3.2 when i write a program with pandas or matplotlib package,then package it using py2exe,i got a error like this: File "C:\Program Files (x86)\Python36-32\lib\site-packages\py2exe\mf3.py", line 215, in _resolve_name raise ValueError('attempted relative import beyond top-level package') ValueError: attempted relative import beyond top-level package.

    my program is a test,no meaningfull functions in it,as follows: import matplotlib.pyplot as plt input('pause') my setup file's content is: from distutils.core import setup import py2exe setup(console=['demo_py2exe_python3.py']) If anyone could help me?thanks very much.

    requires user input unable to reproduce 
    opened by smartlxy 14
  • semantic_version now uses importlib and probably requires a py2exe hook

    semantic_version now uses importlib and probably requires a py2exe hook

    semantic_version 2.8.5 / semantic_version/__init__.py:

    # -*- coding: utf-8 -*-
    # Copyright (c) The python-semanticversion project
    # This code is distributed under the two-clause BSD License.
    
    
    from .base import compare, match, validate, SimpleSpec, NpmSpec, Spec, SpecItem, Version
    
    
    __author__ = "Raphaël Barrois <[email protected]>"
    __version__ = '2.8.5'
    

    That works with py2exe, no problem.

    semantic_version 2.9.0 / semantic_version/__init__.py:

    # -*- coding: utf-8 -*-
    # Copyright (c) The python-semanticversion project
    # This code is distributed under the two-clause BSD License.
    
    
    from .base import compare, match, validate, SimpleSpec, NpmSpec, Spec, SpecItem, Version
    
    
    __author__ = "Raphaël Barrois <[email protected]>"
    try:
        # Python 3.8+
        from importlib.metadata import version
    
        __version__ = version("semantic_version")
    except ImportError:
        import pkg_resources
    
        __version__ = pkg_resources.get_distribution("semantic_version").version
    

    This does not work with py2exe because py2exe only packages the necessary files from the semantic_version/ directory, and nothing from the accompanying semantic_version-2.9.0.dist-info/ directory (NB: 2.8.5 has an equivalent). This then leads to the error:

    Traceback (most recent call last):
      File "semantic_version\__init__.pyc", line 14, in <module>
      File "importlib\metadata\__init__.pyc", line 955, in version
      File "importlib\metadata\__init__.pyc", line 928, in distribution
      File "importlib\metadata\__init__.pyc", line 518, in from_name
    importlib.metadata.PackageNotFoundError: No package metadata was found for semantic_version
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "EDMarketConnector.py", line 55, in <module>
      File "killswitch.pyc", line 12, in <module>
      File "semantic_version\__init__.pyc", line 18, in <module>
      File "pkg_resources\__init__.pyc", line 466, in get_distribution
      File "pkg_resources\__init__.pyc", line 342, in get_provider
      File "pkg_resources\__init__.pyc", line 886, in require
      File "pkg_resources\__init__.pyc", line 772, in resolve
    pkg_resources.DistributionNotFound: The 'semantic_version' distribution was not found and is required by the application```
    bug requires user input 
    opened by Athanasius 12
  • soundfile: cannot load library with bundle_files = 0

    soundfile: cannot load library with bundle_files = 0

    Numpy now works fine with the dll embedded in the exe which is great.

    But with other dlls, like soundfile, the exe fails with either a silent crash or errors like the one in the title. Using a hook to insert it into the bundle does not, alone, solve the issue. In this case it tries to load it via cffi with a path as parameter.

    enhancement wontfix 
    opened by dallouper 12
  • Copying the same DLL from more than one source & check for correct arch

    Copying the same DLL from more than one source & check for correct arch

    We had a headscratcher today, trying to figure out why the GitHub build of our application resulted in a broken install, when it worked perfectly fine from source, and even when built locally.

    We finally tracked this down to how py2exe does both of these:

    Copy DLL C:\hostedtoolcache\windows\Python\3.7.9\x86\DLLs\libcrypto-1_1.dll to dist.win32\
    Copy DLL C:\Program Files\Amazon\AWSCLIV2\libcrypto-1_1.dll to dist.win32\
    

    When we checked a prior build it had also done this double-source copy, but in the other order, so we ended up with the correct version of the file. That 'Amazon' DLL is a 64-bit one so plain doesn't work with our 32-bit program.

    So, two issues:

    1. Why does py2exe copy a DLL twice, from a different source each time ? Surely it should either pick one and stick to it, or alert you that you need to make a decision. Especially important as in some sense the order might be random (we can't easily tell without further investigation if GitHub changed the order of a PATH).
    2. If py2exe knows it's building a 32-bit executable then it should take steps to not copy any 64-bit DLLs, and I assume vice versa.

    Edit: One of these days I'll remember that GitHub issues need the closing triple-backtick on its own line.

    bug 
    opened by Athanasius 12
  • regression: passlib doesnt work with py2exe

    regression: passlib doesnt work with py2exe

    Just ran across a bug in py2exe where it doesn't add passlib automatically and even including passlib in the packages option doesn't help. See the following code:

    from passlib.apps import custom_app_context
    print(custom_app_context.hash('1234'))
    

    It runs under python 3.9 with the following pip reqs:

    py2exe
    passlib==1.7.4
    
    

    If I package it using the following py2exe script it works in py2exe 0.10.2.1 but it fails with the most recent py2exe version (0.11.1.1):

    from distutils.core import setup
    import py2exe #@UnusedImport
    
    setup(
        console= [ { "script": "test.py",}, ],
        options = {"py2exe": {
            "packages": ['passlib'],
            "includes":['configparser'],
     } },
    )
    

    For some reason only a couple of files are added from passlib instead of the whole package

    bug 
    opened by urishab 11
  • zipimport.ZipImportError: can't find module '_bz2'

    zipimport.ZipImportError: can't find module '_bz2'

    Hi, I am getting this error when i try to run a builded exe.

    Traceback (most recent call last):
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 241, in load_module
      File "<frozen zipimport>", line 721, in _get_module_code
    zipimport.ZipImportError: can't find module '_bz2'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<boot hacks>", line 17, in <module>
      File "<boot hacks>", line 3, in patch_certifi
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "certifi\__init__.pyc", line 1, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "certifi\core.pyc", line 12, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "importlib\resources.pyc", line 4, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "importlib\_common.pyc", line 3, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "zipfile.pyc", line 12, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "shutil.pyc", line 22, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "bz2.pyc", line 18, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 110, in load_module
    SystemError: initialization of _bz2 did not return an extension module
    Traceback (most recent call last):
      File "<frozen zipimport>", line 177, in get_data
    KeyError: 'certifi\\cacert.pem'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<frozen zipimport>", line 741, in open_resource
      File "<frozen zipimport>", line 179, in get_data
    OSError: [Errno 0] : 'certifi\\cacert.pem'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "instantrip.py", line 5, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "instaloader\__init__.pyc", line 16, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "instaloader\instaloader.pyc", line 19, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "requests\__init__.pyc", line 120, in <module>
      File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
      File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 627, in _load_backward_compatible
      File "zipextimporter.pyc", line 87, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "requests\utils.pyc", line 40, in <module>
      File "certifi\core.pyc", line 37, in where
      File "contextlib.pyc", line 117, in __enter__
      File "importlib\resources.pyc", line 175, in _path_from_reader
      File "<frozen zipimport>", line 743, in open_resource
    FileNotFoundError: certifi/cacert.pem
    

    Here is my setup.py

    from distutils.core import setup
    import sys
    import py2exe
    
    sys.argv.append('py2exe')
    
    setup(
        options={'py2exe': {
            'bundle_files': 1, 'compressed': True,
            'packages': ['instaloader']
        }},
        console=['instantrip.py']
    )
    

    Could you please point out what i seem to be doing wrong?

    bug 
    opened by 11philip22 11
  • pythoncom and pywintypes module import issue

    pythoncom and pywintypes module import issue

    • test environment

      • windows 10 64bit
      • python 3.8.10 64bit
      • py2exe 0.13.0.0
      • pywin32 305
    • When import pywintypes, pythoncom, I have same problem with https://github.com/py2exe/py2exe/issues/149 AttributeError: module 'pywintypes' has no attribute '__import_pywin32_system_module__'

    • My Workaround

      • change bundle_files to 2
      • change data_files as below
    import pythoncom
    import pywintypes
    ...
        py2exe.freeze(
            ...
            data_files=[
                ("", [pythoncom.__file__]),
                ("", [pywintypes.__file__]),
            ],
            ...
        }
    
    • But, I want to use with bundle_files=0.

    • Is there any way to fix the hook_pythoncom and hook_pywintypes?

    • Below is the result of my analyze.

    • execution result of frozen main.py

    D:\test\dist_py2exe>test.exe
    main: start
    main: frozen=True
    main: __import_pywin32_system_module__=False
    
    • Because pythoncom38.dll and pywintypes38.dll cannot be found in sys.path, ImportError is raised at line 44 at 'import_pywin32_system_module' in pywintypes.py
    • But, it is swallowed by py2exe.hooks.hook_pywintypes and the remaining code in __import_pywin32_system_module__ is not executed.
                raise ImportError(
                    "Module '%s' isn't in frozen sys.path %s" % (modname, sys.path)
                )
    
    • uncomment del py2exe.hooks.hook_pywintypes in main.py
    • ImportError is raised correctly.
    D:\test\dist_py2exe>test.exe
    Traceback (most recent call last):
      File "zipextimporter.pyc", line 96, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "pywintypes.pyc", line 123, in <module>
      File "pywintypes.pyc", line 44, in __import_pywin32_system_module__
    ImportError: Module 'pywintypes' isn't in frozen sys.path ['D:\\test\\dist_py2exe\\test.exe']
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "main.py", line 5, in <module>
      File "zipextimporter.pyc", line 131, in load_module
    zipimport.ZipImportError: can't find module pywintypes
    
    • change data_files in dist_py2exe.py
    import pythoncom
    import pywintypes
    ...
        py2exe.freeze(
            ...
            data_files=[
                ("", [pythoncom.__file__]),
                ("", [pywintypes.__file__]),
            ],
            ...
        }
    
    D:\test\dist_py2exe>dir
    2022-12-20  15:31           717,824 pythoncom38.dll
    2022-12-20  15:31           140,800 pywintypes38.dll
    2022-12-20  16:33         9,409,558 test.exe
    
    D:\test\dist_py2exe>test.exe
    Traceback (most recent call last):
      File "zipextimporter.pyc", line 96, in load_module
      File "<frozen zipimport>", line 259, in load_module
      File "pywintypes.pyc", line 123, in <module>
      File "pywintypes.pyc", line 113, in __import_pywin32_system_module__
      File "<frozen importlib._bootstrap>", line 556, in module_from_spec
      File "<frozen importlib._bootstrap_external>", line 1166, in create_module
      File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    ImportError: DLL load failed while importing pywintypes: 지정된 모듈을 찾을 수 없습니다.
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "main.py", line 4, in <module>
      File "zipextimporter.pyc", line 131, in load_module
    zipimport.ZipImportError: can't find module pywintypes
    
    • pythoncom38.dll and pywintypes38.dll depend on python38.dll
    • change bundle_files from 0 to 2 in dist_py2exe.py
    D:\test\dist_py2exe>dir
    2021-05-03  11:54         3,406,016 libcrypto-1_1.dll
    2021-05-03  11:54            32,792 libffi-7.dll
    2021-05-03  11:54           690,368 libssl-1_1.dll
    2021-05-03  11:54         4,211,376 python38.dll
    2022-12-20  15:31           717,824 pythoncom38.dll
    2022-12-20  15:31           140,800 pywintypes38.dll
    2022-12-20  16:41         3,630,883 test.exe
    
    • Good: __import_pywin32_system_module__=True
    D:\test\dist_py2exe>test.exe
    main: start
    main: frozen=True
    main: __import_pywin32_system_module__=True
    
    • dist_py2exe.py source
    from typing import List
    
    import py2exe
    import py2exe.hooks
    
    excludes: List[str] = [
        '_gtkagg', '_tkagg', 'bsddb', 'curses', 'pywin.debugger', 'pywin.debugger.dbgcon',
        'pywin.dialogs', 'tcl', 'tkinter'
    ]
    
    target_1 = {
        "script": "main.py",
        "icon_resources": [],
        "bitmap_resources": [],
        "other_resources": [],
        "dest_base": "test",
    }
    
    def main() -> None:
        # del py2exe.hooks.hook_pywintypes
        # del py2exe.hooks.hook_pythoncom
    
        py2exe.freeze(
            console=[target_1],
            data_files=None,
            zipfile=None,
            options={
                "includes": [],
                "excludes": excludes,
                "packages": [],
                "dll_excludes": [],
                "dist_dir": "dist_py2exe",
                "compressed": 1,
                "optimize": 1,
                "bundle_files": 0,
                "verbose": 4,
            },
        )
    
    if __name__ == "__main__":
        main()
    
    • main.py source
    import sys
    
    #import pythoncom
    import pywintypes
    
    def main() -> None:
        print("main: start")
        print(f"main: frozen={hasattr(sys, 'frozen')}")
        print(f"main: __import_pywin32_system_module__={hasattr(pywintypes, '__import_pywin32_system_module__')}")
    
    if __name__ == "__main__":
        main()
    
    # Magic utility that "redirects" to pywintypesxx.dll
    import importlib.util, importlib.machinery, sys, os
    
    
    def __import_pywin32_system_module__(modname, globs):
        # This has been through a number of iterations.  The problem: how to
        # locate pywintypesXX.dll when it may be in a number of places, and how
        # to avoid ever loading it twice.  This problem is compounded by the
        # fact that the "right" way to do this requires win32api, but this
        # itself requires pywintypesXX.
        # And the killer problem is that someone may have done 'import win32api'
        # before this code is called.  In that case Windows will have already
        # loaded pywintypesXX as part of loading win32api - but by the time
        # we get here, we may locate a different one.  This appears to work, but
        # then starts raising bizarre TypeErrors complaining that something
        # is not a pywintypes type when it clearly is!
    
        # So in what we hope is the last major iteration of this, we now
        # rely on a _win32sysloader module, implemented in C but not relying
        # on pywintypesXX.dll.  It then can check if the DLL we are looking for
        # lib is already loaded.
        # See if this is a debug build.
        suffix = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else ""
        filename = "%s%d%d%s.dll" % (
            modname,
            sys.version_info[0],
            sys.version_info[1],
            suffix,
        )
        if hasattr(sys, "frozen"):
            # If we are running from a frozen program (py2exe, McMillan, freeze)
            # then we try and load the DLL from our sys.path
            # XXX - This path may also benefit from _win32sysloader?  However,
            # MarkH has never seen the DLL load problem with py2exe programs...
            for look in sys.path:
                # If the sys.path entry is a (presumably) .zip file, use the
                # directory
                if os.path.isfile(look):
                    look = os.path.dirname(look)
                found = os.path.join(look, filename)
                if os.path.isfile(found):
                    break
            else:
                raise ImportError(
                    "Module '%s' isn't in frozen sys.path %s" % (modname, sys.path)
                )
        else:
            # First see if it already in our process - if so, we must use that.
            import _win32sysloader
    
            found = _win32sysloader.GetModuleFilename(filename)
            if found is None:
                # We ask Windows to load it next.  This is in an attempt to
                # get the exact same module loaded should pywintypes be imported
                # first (which is how we are here) or if, eg, win32api was imported
                # first thereby implicitly loading the DLL.
    
                # Sadly though, it doesn't quite work - if pywintypesxx.dll
                # is in system32 *and* the executable's directory, on XP SP2, an
                # import of win32api will cause Windows to load pywintypes
                # from system32, where LoadLibrary for that name will
                # load the one in the exe's dir.
                # That shouldn't really matter though, so long as we only ever
                # get one loaded.
                found = _win32sysloader.LoadModule(filename)
            if found is None:
                # Windows can't find it - which although isn't relevent here,
                # means that we *must* be the first win32 import, as an attempt
                # to import win32api etc would fail when Windows attempts to
                # locate the DLL.
                # This is most likely to happen for "non-admin" installs, where
                # we can't put the files anywhere else on the global path.
    
                # If there is a version in our Python directory, use that
                if os.path.isfile(os.path.join(sys.prefix, filename)):
                    found = os.path.join(sys.prefix, filename)
            if found is None:
                # Not in the Python directory?  Maybe we were installed via
                # easy_install...
                if os.path.isfile(os.path.join(os.path.dirname(__file__), filename)):
                    found = os.path.join(os.path.dirname(__file__), filename)
    
            # There are 2 site-packages directories - one "global" and one "user".
            # We could be in either, or both (but with different versions!). Factors include
            # virtualenvs, post-install script being run or not, `setup.py install` flags, etc.
    
            # In a worst-case, it means, say 'python -c "import win32api"'
            # will not work but 'python -c "import pywintypes, win32api"' will,
            # but it's better than nothing.
    
            # We use the same logic as pywin32_bootstrap to find potential location for the dll
            # Simply import pywin32_system32 and look in the paths in pywin32_system32.__path__
    
            if found is None:
                import pywin32_system32
    
                for path in pywin32_system32.__path__:
                    maybe = os.path.join(path, filename)
                    if os.path.isfile(maybe):
                        found = maybe
                        break
    
            if found is None:
                # give up in disgust.
                raise ImportError("No system module '%s' (%s)" % (modname, filename))
        # After importing the module, sys.modules is updated to the DLL we just
        # loaded - which isn't what we want. So we update sys.modules to refer to
        # this module, and update our globals from it.
        old_mod = sys.modules[modname]
        # Load the DLL.
        loader = importlib.machinery.ExtensionFileLoader(modname, found)
        spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=found)
        mod = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(mod)
    
        # Check the sys.modules[] behaviour we describe above is true...
        assert sys.modules[modname] is mod
        # as above - re-reset to the *old* module object then update globs.
        sys.modules[modname] = old_mod
        globs.update(mod.__dict__)
    
    
    __import_pywin32_system_module__("pywintypes", globals())
    
    wontfix requires user input 
    opened by marunguy 7
  • matplotlib and wx

    matplotlib and wx

    This is somehow related to #71 .

    The hook for matplotlib looks like this:

    image

    How about I am using wxPython for my interface?

    This ends up putting "wx" in the list of excluded packages, and of course py2exe bombs out like this:

    Traceback (most recent call last): File "C:\Users\Whatever\MyProject\setup.py", line 1404, in BuildPy2Exe(architecture) File "C:\Users\Whatever\MyProject\setup.py", line 739, in BuildPy2Exe setup( File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\setuptools_distutils\core.py", line 148, in setup return run_commands(dist) File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\setuptools_distutils\core.py", line 163, in run_commands dist.run_commands() File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\setuptools_distutils\dist.py", line 967, in run_commands self.run_command(cmd) File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\setuptools_distutils\dist.py", line 986, in run_command cmd_obj.run() File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\py2exe\distutils_buildexe.py", line 204, in run self._run() File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\py2exe\distutils_buildexe.py", line 284, in _run builder.analyze() File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\py2exe\runtime.py", line 176, in analyze mf.import_hook(modname) File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\py2exe\vendor\modulefinder.py", line 215, in import_hook q, tail = self.find_head_package(parent, name) File "C:\Users\Whatever\python-3.9.10.amd64\lib\site-packages\py2exe\vendor\modulefinder.py", line 284, in find_head_package raise ImportError(f'Module {name} is in the "excludes" list') ImportError: Module wx is in the "excludes" list

    bug 
    opened by infinity77 3
  • Unable to run eel exe using py2exe

    Unable to run eel exe using py2exe

    py2exe ==0.13.0.0 Eel==0.15.0 python == 3.8.10

    Getting issue while running exe that is created using py2exe - File "eel_init_.pyc", line 21, in File "pkg_resources_init_.pyc", line 1154, in resource_filename File "pkg_resources_init_.pyc", line 1754, in get_resource_filename NotImplementedError: resource_filename() only supported for .egg, not .zip

    requires user input 
    opened by s-t123 2
  • The system cannot find the path specified: `dist\library.zip\PySide6`

    The system cannot find the path specified: `dist\library.zip\PySide6`

    demo.py:

    """Demo"""
    from PySide6.QtWidgets import QApplication, QMainWindow
    
    application = QApplication()
    window = QMainWindow()
    window.show()
    application.exec()
    

    demo.bat:

    @echo off
    pip install pyside6-essentials
    python demo.py
    python -c "import py2exe; py2exe.freeze(console=['demo.py'])"
    dist\demo.exe
    

    Output:

    [...]
    Building 'dist\demo.exe'.
    Traceback (most recent call last):
      File "demo.py", line 2, in <module>
        from PySide6.QtWidgets import QApplication, QMainWindow
      File "PySide6\__init__.pyc", line 123, in <module>
      File "PySide6\__init__.pyc", line 111, in _find_all_qt_modules
    FileNotFoundError: [WinError 3] The system cannot find the path specified: 'C:\\Code\\Project\\dist\\library.zip\\PySide6'
    
    bug 
    opened by bersbersbers 3
  • Include site module?

    Include site module?

    I see that the site module is excluded from the builds in hooks.py, and Py_NoSiteFlag and Py_NoUserSiteDirectory are set when initializing the interpreter. These lines predate the import into github, so I'm wondering if you have any insight into why this is the case (or if not, objections to including it). I suppose it makes some sense if the goal is to completely isolate the app from any python installed on the system, but with TortoioseHg, I'd like to be able to pip-install extensions to the user site directory and have that visible to the app. Additionally, importing site adds several things to __builtins__[1], which means Mercurial behaves slightly differently in some cases, depending on if it's built with py2exe or a different method. Opting into Py_NoSiteFlag and Py_NoUserSiteDirectory as a build time option seems fine, if you have compatibility concerns in the default case.

    [1] https://docs.python.org/3/library/constants.html#constants-added-by-the-site-module

    question 
    opened by mharbison72 8
Releases(v0.13.0.0)
Psgcompiler A PySimpleGUI Application - Transform your Python programs in Windows, Mac, and Linux binary executables

psgcompiler A PySimpleGUI Application "Compile" your Python programs into an EXE for Windows, an APP for Mac, and a binary for Linux Installation Old-

PySimpleGUI 77 Jan 7, 2023
py2app is a Python setuptools command which will allow you to make standalone Mac OS X application bundles and plugins from Python scripts.

py2app is a Python setuptools command which will allow you to make standalone Mac OS X application bundles and plugins from Python scripts. py2app is

Ronald Oussoren 222 Dec 30, 2022
Freeze (package) Python programs into stand-alone executables

PyInstaller Overview PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app withou

PyInstaller 9.9k Jan 8, 2023
Nuitka Organization 8k Jan 7, 2023
Build Windows installers for Python applications

Pynsist is a tool to build Windows installers for your Python applications. The installers bundle Python itself, so you can distribute your applicatio

Thomas Kluyver 818 Jan 5, 2023
Python virtualenvs in Debian packages

dh-virtualenv Contents Overview Presentations, Blogs & Other Resources Using dh-virtualenv How does it work? Running tests Building the package in a D

Spotify 1.5k Dec 16, 2022
A tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine or expire obfuscated scripts.

PyArmor Homepage (中文版网站) Documentation(中文版) PyArmor is a command line tool used to obfuscate python scripts, bind obfuscated scripts to fixed machine

Dashingsoft 1.9k Jan 1, 2023
shiv is a command line utility for building fully self contained Python zipapps as outlined in PEP 441, but with all their dependencies included.

shiv shiv is a command line utility for building fully self-contained Python zipapps as outlined in PEP 441, but with all their dependencies included!

LinkedIn 1.5k Dec 28, 2022
Core utilities for Python packages

packaging Reusable core utilities for various Python Packaging interoperability specifications. This library provides utilities that implement the int

Python Packaging Authority 451 Jan 4, 2023
A library and tool for generating .pex (Python EXecutable) files

PEX Contents Overview Installation Simple Examples Integrating pex into your workflow Documentation Development Contributing Overview pex is a library

Pants Build 2.2k Jan 1, 2023
A modern Python application packaging and distribution tool

PyOxidizer PyOxidizer is a utility for producing binaries that embed Python. The over-arching goal of PyOxidizer is to make complex packaging and dist

Gregory Szorc 4.5k Jan 7, 2023
Subpar is a utility for creating self-contained python executables. It is designed to work well with Bazel.

Subpar Subpar is a utility for creating self-contained python executables. It is designed to work well with Bazel. Status Subpar is currently owned by

Google 550 Dec 27, 2022
Python Wheel Obfuscator

pywhlobf obfuscates your wheel distribution by compiling python source file to shared library.

Hunt Zhan 79 Dec 22, 2022
FreezeUI is a python package that creates applications using cx_freeze and GUI by converting .py to .exe .

FreezeUI is a python package use to create cx_Freeze setup files and run them to create applications and msi from python scripts (converts .py to .exe or .msi .

null 4 Aug 25, 2022
Python-easy-pack For Linux/Unix, Changed by laman28

Python-easy-pack For Linux/Unix, Changed by laman28

LMFS 2 Jan 28, 2022
A library which implements low-level functions that relate to packaging and distribution of Python

What is it? Distlib is a library which implements low-level functions that relate to packaging and distribution of Python software. It is intended to

Python Packaging Authority 29 Oct 11, 2022
allow windows programs to call dssp/mkdssp command from wsl; rework biopython on windows (PDB -> dssp -> fasta)

dssp-wsl Converting PDB (Protein Data Bank) file format to DSSP file format is required for generating datasets of peptides and their secondary struct

Taine Zhao 1 Feb 23, 2022
PyPacker: a dumb little script for turning Python apps into standalone executable packages on Windows

PyPacker: a dumb little script for turning Python apps into standalone executable packages on Windows PyPacker is my attempt at creating a way to make

Serdar Yegulalp 9 Mar 15, 2022
This repo is a C++ version of yolov5_deepsort_tensorrt. Packing all C++ programs into .so files, using Python script to call C++ programs further.

yolov5_deepsort_tensorrt_cpp Introduction This repo is a C++ version of yolov5_deepsort_tensorrt. And packing all C++ programs into .so files, using P

null 41 Dec 27, 2022
Create standalone executables from Python scripts, with the same performance and is cross-platform.

About cx_Freeze cx_Freeze creates standalone executables from Python scripts, with the same performance, is cross-platform and should work on any plat

Marcelo Duarte 1k Jan 4, 2023