Problem packaging with py2exe

Hi,
I have a wx program that i am trying to package with py2exe. I based my
setup.py on the example that adds an Inno Setup installer. The exe installs
correctly, but every time I run it, I get the following error in the log:
Traceback (most recent call last):
  File "gui.py", line 1, in ?
  File "wx\__init__.pyo", line 45, in ?
  File "wx\_core.pyo", line 4, in ?
  File "wx\_core_.pyo", line 12, in ?
  File "wx\_core_.pyo", line 10, in __load
ImportError: DLL load failed: The specified module could not be found.

even if the program launches.

Also, the program has a .ico file that is used for the app's icon and for the
taskbar icons. It is placed in the same location in the exe, but when the
program starts, I get an error dialog with the message:
Can't load image from file c-get.ico: file does not exist.

The manifest doen't seem to work too. When installed on an XP machine, the
widgets like they're on Windows 2000.

What might be wrong with my setup.py? Here it is:

# setup.py
from distutils.core import setup
import glob
import py2exe
import matplotlib
import sys
import os

class InnoScript:
    def __init__(self,
                 name,
                 lib_dir,
                 dist_dir,
                 windows_exe_files = [],
                 lib_files = [],
                 version = "1.0"):
        self.lib_dir = lib_dir
        self.dist_dir = dist_dir
        if not self.dist_dir[-1] in "\\/":
            self.dist_dir += "\\"
        self.name = name
        self.version = version
        self.windows_exe_files = [self.chop(p) for p in windows_exe_files]
        self.lib_files = [self.chop(p) for p in lib_files]

    def chop(self, pathname):
        assert pathname.startswith(self.dist_dir)
        return pathname[len(self.dist_dir):]
    
    def create(self, pathname="dist\\C-GET.iss"):
        self.pathname = pathname
        ofi = self.file = open(pathname, "w")
        print >> ofi, "; WARNING: This script has been created by py2exe.
Changes to this script"
        print >> ofi, "; will be overwritten the next time py2exe is run!"
        print >> ofi, r"[Setup]"
        print >> ofi, r"AppName=%s" % self.name
        print >> ofi, r"AppVerName=%s %s" % (self.name, self.version)
        print >> ofi, r"DefaultDirName={pf}\%s" % self.name
        print >> ofi, r"DefaultGroupName=%s" % self.name
        print >> ofi, r"Compression=lzma/max"
        print >> ofi

        print >> ofi, r"[Files]"
        for path in self.windows_exe_files + self.lib_files:
            print >> ofi, r'Source: "%s"; DestDir: "{app}\%s"; Flags:
ignoreversion' % (path, os.path.dirname(path))
        print >> ofi

        print >> ofi, r"[Icons]"
        for path in self.windows_exe_files:
            print >> ofi, r'Name: "{group}\%s"; Filename: "{app}\%s"' % \
                  (self.name, path)
        print >> ofi, 'Name: "{group}\Uninstall %s";
Filename: "{uninstallexe}"' % self.name

        print >> ofi, r"[Files]"
        for path in self.windows_exe_files + self.lib_files:
            print >> ofi, r'Source: "%s"; DestDir: "{app}\%s"; Flags:
ignoreversion' % (path, os.path.dirname(path))

        print >> ofi, """
[Tasks]
Name: "quicklaunchicon"; Description: "Create Quick Launch icon.";
GroupDescription: "Additional icons:"; Flags: checkedonce
Name: "desktopicon"; Description: "Create Desktop icon.";
GroupDescription: "Additional icons:"; Flags: checkedonce
        """

        print >> ofi, r"[Icons]"
        for path in self.windows_exe_files:
            print >> ofi, r'Name: "{group}\%s"; Filename: "{app}\%s"' % \
                  (self.name, path)
        print >> ofi, 'Name: "{group}\Uninstall %s";
Filename: "{uninstallexe}"' % self.name
        print >> ofi, 'Name: "{userappdata}\Microsoft\Internet Explorer\Quick
Launch\%s"; Filename: "{app}\%s"; Tasks: quicklaunchicon' % (self.name, path)
        print >> ofi, 'Name: "{userdesktop}\%s"; Filename: "{app}\%s"; Tasks:
desktopicon' % (self.name, path)

    def compile(self):
        try:
            import ctypes
        except ImportError:
            try:
                import win32api
            except ImportError:
                import os
                os.startfile(self.pathname)
            else:
                print "Ok, using win32api."
                win32api.ShellExecute(0, "compile",
                                                self.pathname,
                                                None,
                                                None,
                                                0)
        else:
            print "Cool, you have ctypes installed."
            res = ctypes.windll.shell32.ShellExecuteA(0, "compile",
                                                      self.pathname,
                                                      None,
                                                      None,
                                                      0)
            if res < 32:
                raise RuntimeError, "ShellExecute failed, error %d" % res

···

################################################################

from py2exe.build_exe import py2exe

class build_installer(py2exe):
    # This class first builds the exe file(s), then creates a Windows installer.
    # You need InnoSetup for it.
    def run(self):
        # First, let py2exe do it's work.
        py2exe.run(self)

        lib_dir = self.lib_dir
        dist_dir = self.dist_dir
        
        # create the Installer, using the files py2exe has created.
        script = InnoScript("C-GET",
                            lib_dir,
                            dist_dir,
                            self.windows_exe_files,
                            self.lib_files)
        print "*** creating the inno setup script***"
        script.create()
        print "*** compiling the inno setup script***"
        script.compile()
        # Note: By default the final setup.exe will be in an Output
subdirectory.

manifest_template = """
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<assemblyIdentity
    version='5.0.0.0'
    processorArchitecture='x86'
    name='%(prog)s'
    type='win32'
/>
<description>%(prog)s</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type='win32'
            name='Microsoft.Windows.Common-Controls'
            version='6.0.0.0'
            processorArchitecture='X86'
            publicKeyToken='6595b64144ccf1df'
            language='*'
        />
    </dependentAssembly>
</dependency>
  <trustInfo xmlns='urn:schemas-microsoft-com:asm.v3'>
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level='AsInvoker'
          uiAccess='false'/>
        </requestedPrivileges>
       </security>
  </trustInfo>
</assembly>
"""

RT_MANIFEST = 32

cget = dict(
    script = "gui.py",
    other_resources = [(RT_MANIFEST, 1, manifest_template % dict(prog="C-
GET"))],
    dest_base = r"C-GET",
    icon_resources = [(1, 'c-get.ico')])

def getfiles(dire=matplotlib.get_data_path()):
    files = []
    dirs = {}
    l = os.listdir(dire)
    for i in l:
        if i == "fonts":
            t = os.path.join(dire, i)
            for j in os.listdir(t):
                k = os.path.join(t,j)
                for s in os.listdir(k):
                    files.append(os.path.join(k,s))
                dirs[i+"\\"+j] = files
                files = []
        elif i == "images":
            t = os.path.join(dire, i)
            for j in os.listdir(t):
                files.append(os.path.join(t,j))
            dirs[i] = files
            files = []
    return dirs
d = getfiles()
setup(windows=[cget],
      options = {'py2exe': { 'includes': 'matplotlib.numerix.random_array',
                                'excludes':
['_nc_backend_agg','_gtkagg', '_tkagg','_gtkagg','_na_backend_agg','_na_backend_
gdk',
                                         '_nc_backend_agg','_nc_backend_gdk','_n
s_backend_agg','_ns_backend_gdk',
                                         '_tkagg','backend_agg','backend_agg2','
backend_cairo',
                                         'backend_emf','backend_fltkagg','backen
d_gd','backend_gdk','backend_gtk',
                                         'backend_gtkagg','backend_gtkcairo','ba
ckend_paint','backend_pdf','backend_ps',
                                         'backend_qt','backend_qt4','backend_qt4
agg','backend_qtagg','backend_svg',
                                        'backend_tkagg','setuptools',
                                         'pywin', 'pywin.debugger', 'pywin.debug
ger.dbgcon','pywin.dialogs', 'pywin.dialogs.list',
                                             'tcl','Tkinter','Tkconstants', 'ema
il', 'pytz','curses','calendar','cmd',
                                             'BaseHTTPServer','SocketServer','_L
WPCookieJar','_MozillaCookieJar','ftplib',
                                             'cookielib','ConfigParser','webbrow
ser'],
                                "packages":
["encodings", "matplotlib.numerix"],
                                'dll_excludes': ['libgdk-win32-2.0-
0.dll','libgobject-2.0-0.dll',"tcl84.dll", "tk84.dll"],
                                'typelibs':[('{565783C6-CB41-11D1-8B02-
00600806D9B6}', 0, 1, 2)],
                                      # create a compressed zip archive
                                'compressed': 1,
                                'optimize': 2,
                          }
                   },
      zipfile = r"lib\sharedlib.zip",
      data_files=[('.',
                   
['sample1.qap','sample2.qap','MFC71.dll','sample1.tsp', 'QAPReports', 'TSPReport
s', 'c-get.ico',
                    'gdiplus.dll','c-get.png']),
                  ('lib\\matplotlibdata\\'+d.keys()[0],d[d.keys()[0]]),
                    ('lib\\matplotlibdata\\'+d.keys()[1],d[d.keys()[1]]),
                    ('lib\\matplotlibdata\\'+d.keys()[2],d[d.keys()[2]]),
                    ('lib\\matplotlibdata\\'+d.keys()[3],d[d.keys()[3]]),
                    ('lib\\matplotlibdata',[r'C:\Python24\Lib\site-
packages\matplotlib\mpl-data\matplotlibrc']),
                   #('matplotlibdata',[r'C:\Python24\Lib\site-
packages\matplotlib\mpl-data\matplotlibrc']),
                  ('src',
[r'src\tsp_compute.py',r'src\qap_compute.py',r'src\condor.py'])
                  ],
      cmdclass = {"py2exe": build_installer},
      )

Hi Simon,

simon kagwe wrote:

Hi,
I have a wx program that i am trying to package with py2exe. I based my setup.py on the example that adds an Inno Setup installer. The exe installs correctly, but every time I run it, I get the following error in the log:
Traceback (most recent call last):
  File "gui.py", line 1, in ?
  File "wx\__init__.pyo", line 45, in ?
  File "wx\_core.pyo", line 4, in ?
  File "wx\_core_.pyo", line 12, in ?
  File "wx\_core_.pyo", line 10, in __load
ImportError: DLL load failed: The specified module could not be found.
  

You have a lot of "excludes" are you sure that they are all not needed? I would start with not excluding anything and then add them back in.

even if the program launches.

Also, the program has a .ico file that is used for the app's icon and for the taskbar icons. It is placed in the same location in the exe, but when the program starts, I get an error dialog with the message:
Can't load image from file c-get.ico: file does not exist.
  

Try this:
icon_resources = [(1, r"c-get.ico")],

The manifest doen't seem to work too. When installed on an XP machine, the widgets like they're on Windows 2000.
  

Change this line from:

RT_MANIFEST = 32

to:
RT_MANIFEST = 24

Werner

Werner F. Bruhin wrote:

Also, the program has a .ico file that is used for the app's icon and for the taskbar icons. It is placed in the same location in the exe, but when the program starts, I get an error dialog with the message:
Can't load image from file c-get.ico: file does not exist.
  

Try this:
icon_resources = [(1, r"c-get.ico")],

That will take care of embedding it in the exe so it is used for file listings in Windows Explorer and what-not, but you'll still want to have a way to find it at runtime so you can use it for self.SetIcon and etc. When you say it is placed in the same location as the exe it sounds like you are assuming that it will automatically be found there if you don't specify a path name. That is not the case, it will only be found that way if the app happens to be running with that dir as the current working dir, which you can't guarantee. Best thing to do is to use one of the dirs provided by wx.StandardPaths, but you can also use something like os.path.dirname(sys.argv[0]) to find where the image file is located.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!