Packaging DLLs with executables made by py2exe

October 9th, 2008 at 10:26 am

I’m a happy user of py2exe for packaging Python programs into stand-alone Windows executables. The executables it creates are quite large (almost 7 MB for a program with a wxPython GUI and a few custom libraries), but they load and work very quickly and provide a very comfortable means for sending pre-packaged Python programs to people who can’t or won’t install Python, wxPython and a ton of other libraries just to make a program work.

Yesterday I had a first problem with py2exe packed executables. A user installed the .exe on a cleanly installed Windows PC, and got the error:

Traceback (most recent call last):
  File "perpsearch.py", line 6, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "wx\__init__.pyo", line 45, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "wx\_core.pyo", line 4, in <module>
  File "zipextimporter.pyo", line 98, in load_module
ImportError: MemoryLoadLibrary failed loading wx\_core_.pyd

After some Googling, the solution turned out to be the lack of MSVCP71.DLL on his computer. Note, this is not MSVCR71.DLL which is placed by py2exe in the dist directory, but another DLL, upon which wxPython depends. This DLL usually exists on Windows XP / Vista computers because it comes with many applications, but for fresh installs it’s missing.

Thankfully, py2exe has a solution for including various DLLs inside the created .exe – described here. Basically, you have to override the function used by py2exe to decide whether to include a system DLL in the executable:

# setup.py
from distutils.core import setup
import py2exe,sys,os

origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname):
        if os.path.basename(pathname).lower() in ("msvcp71.dll", "dwmapi.dll"):
                return 0
        return origIsSystemDLL(pathname)
py2exe.build_exe.isSystemDLL = isSystemDLL

[remainder of setup.py stuff]

This solves the problem and the executable can now run even on platforms that don’t include MSVCP71.DLL.

This still leaves us with MSVCR71.DLL. This DLL is actually loaded by the executable itself, so it can’t be packaged inside. If the target system is missing it, it must be packaged along-side the executable (or inside Windows’ system directory by an installer). Every Windows XP SP2+ or Vista computer should have it, though, even after a fresh install.

Related posts:

  1. Compiling C DLLs and using them from Perl
  2. A Tetris clone in Python / wxPython
  3. Tetris implemented in PyQt
  4. Problem passing arguments to Python scripts on Windows
  5. a quest for difference

4 Responses to “Packaging DLLs with executables made by py2exe”

  1. Informático de GuardiaNo Gravatar Says:

    Can you tell me if py2exe works with Python 3.0.1 or greater?
    Thanks go in advance

  2. iainNo Gravatar Says:

    You can use inno setup to package py2exe executables and other files into a single installer.

  3. elibenNo Gravatar Says:

    @Informático de Guardia,

    I have no idea about their Python 3 compatibility – but you can google it or look at the py2exe mailing list.

  4. BobNo Gravatar Says:

    I am having an issue with create an .exe of a program I created. The program is of a PyQt4 Gui around a pyserial python code. I am having an issue with: MSVCP90.dll not being found. I have then tried to bypass the dll and can create a dist folder however when I click on the .exe folder my application does not run