views:

1102

answers:

5

I'm very new to Python in general, but I made an app in Python 2.6 / wxPython 2.8 that works perfectly when I run it through Python. But I wanted to go a step further and be able to deploy it as a Windows executable, so I've been trying out py2exe. But I haven't been able to get it to work. It would always compile an exe, but when I actually try to run that it barks some cryptic error message. At first they were simple messages saying it couldn't find certain DLLs, but even after giving it all the DLLs it wanted, it now returns this:

The application failed to initialize properly (0xc0000142).
Click OK to terminate the application.

So I broke things down and just made a very, very simple application utilizing wxPython just to see if that would work, or if some of the more complicated features of my original app were getting in the way. But even my simple test returned the same error. Here's the code for the simple test script:

import wx

class MainWindow(wx.Frame):

 def __init__(self, parent, id, title):
  wx.Frame.__init__(self, parent, wx.ID_ANY, title, style=wx.DEFAULT_FRAME_STYLE ^ wx.MAXIMIZE_BOX)
  panel = wx.Panel(self, -1, style = wx.TAB_TRAVERSAL | wx.CLIP_CHILDREN | wx.FULL_REPAINT_ON_RESIZE)
  main_sizer = wx.BoxSizer(wx.VERTICAL)

  testtxt = wx.StaticText(panel, -1, label='This is a test!')
  main_sizer.Add(testtxt, 0, wx.ALIGN_CENTER)

  panel.SetSizerAndFit(main_sizer)
  self.Show(1)
  return

app = wx.PySimpleApp()
frame = MainWindow(None, -1, 'Test App')
app.MainLoop()

And here's the py2exe setup script I used:

#!/usr/bin/python

from distutils.core import setup
import py2exe

manifest = """
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<assemblyIdentity
    version="0.64.1.0"
    processorArchitecture="x86"
    name="Controls"
    type="win32"
/>
<description>Test Program</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="X86"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
</assembly>
"""

setup(
    windows = [
        {
            "script": "testme.py",
            "icon_resources": [(1, "testme.ico")],
            "other_resources": [(24,1, manifest)]
        }
    ],
  data_files=["testme.ico"]

)

Then I run python setup.py py2exe, it generates the EXE file, warns about some DLL files (which I subsequently copy into the dist directory), but then when I try to run the EXE, I get the error I quoted above immediately.

A: 

I've used py2exe before and I've never run across a situation like this....

However, it sounds like missing dependencies are your problem.....

Does the packaged program work on your machine but not on others?

If so, run the packaged application within DEPENDS (dependency walker) on both machines and compare to hopefully discern which packages didn't get included.

Good Luck

CMB
By "packaged program" do you mean the generated exe? Or just running the script directly through Python? Anyways, if I run `python testme.py` from the command line, that works fine. But the point of running this through py2exe is that I want to be able to deploy it to computers that *don't* have Python installed. But right now it's not working on *any* computer, Python or not, when I compile it with py2exe.
SoaperGEM
Packaged Program = Generated Exe.The exe should run fine on the machine that produced it. Run it on that machine with dependency walker to see the explicit list of libraries loaded.Then turn around and do this on a machine that fails. The difference will point you to a solution.
CMB
That was my point all along... the packaged program *DOES NOT* run fine on the machine that produced it. Hence the title.
SoaperGEM
The question was not entirely clear to me. Still, you can use depends on the application to view what did not load successfully.
CMB
A: 

You are not supposed to copy ALL of the .dlls it complains about! Some of them are Windows system files, and they are present in the correct places on the system. If you copy them into the dist folder, things won't work correctly.

In general, you only want to copy .dlls which are specific to your application. Not system .dlls. In some situations you may need to ship vcredist_xx.exe in your installer to get the MSVC runtime on the system. You should never try to ship those .dlls files "raw" by yourself. Use the redist package, it will save you time and frustration.

Have you tried following the directions here: http://wiki.wxpython.org/SmallApp ?

Christopher
I tried those directions, and here's what happened. 1. Tried running `python setup.py py2exe --icon=SmallApp.ico`, got this error: `error: option --icon not recognized`. 2. Tried running `python setup.py py2exe`, got this error: `error: error in setup.cfg: command 'py2exe' has no such option 'version_legalcopyright'`. 3. Deleted the setup.cfg file and tried re-running `python setup.py py2exe`, py2exe *appeared* to run fine, it created build and dist directories with files in them--except it did not create an EXE file in dist! (other than just w9xpopen.exe, which does nothing on its own)
SoaperGEM
4. Modified the setup.py file in the directions to instead match the one I posted above in the question here (except changed references from `testme` to `smallapp`), and it compiled fine, produced an EXE fine, but the EXE it created has exactly the same error: Application failed to initialize properly.
SoaperGEM
A: 

Are you sure that you give the same dlls that the one used by wxPython.

The vc++ dlls used by wxpython can be downloaded from the wxpython download page. Did you try these one?

luc
When I try to run the EXE without copying DLLs, I actually get this error: This application has failed to start because MSVCR90.dll was not found. Re-installing the application may fix this problem.Then I copy msvcr90.dll to the dist folder and get the "application failed to initialize properly" error mentioned above. AFAIK, this DLL is from the VC++ package.
SoaperGEM
Did you also install Visual C++ redistruable package?
luc
SoaperGEM
+3  A: 

Note that there is a later version of the Visual C++ 2008 Redistributable package: SP1. However, both the SP1 and the earlier release don't install the DLLs into the path. As the download page says (my emphasis):

This package installs runtime components of C Runtime (CRT), Standard C++, ATL, MFC, OpenMP and MSDIA libraries. For libraries that support side-by-side deployment model (CRT, SCL, ATL, MFC, OpenMP) they are installed into the native assembly cache, also called WinSxS folder, on versions of Windows operating system that support side-by-side assemblies.

You will probably find these files in the %WINDIR%\WinSxS folder and not in the path.What I think you need to do is incorporate the manifest information for the relevant DLLs (found in %WINDIR%\WinSxS\Manifests) into your setup.py. I added the following section:

<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.VC90.CRT"
            version="9.0.30729.4918"
            processorArchitecture="X86"
            publicKeyToken="1fc8b3b9a1e18e3b"
            language="*"
        />
    </dependentAssembly>
</dependency>

immediately after the existing <dependency> section, and rebuilt the exe: it ran without problems. Note: depending on exactly what version of the Visual C++ files you installed, the above info may not be exactly correct. Look at the manifests on your system and use the correct version, publicKeyToken etc.

Alternatively, look at this answer for how to deploy the DLLs with your application (as opposed to assuming they already exist on the target system). Oh ... I see you asked that original question ;-)

Vinay Sajip
Adding that `<dependency>` did it! Thank you so much!
SoaperGEM
By the way, given a DLL file, how do you find the publicKeyToken for it? For instance, I actually have version 9.0.30729.1 of the DLL above; how would I go about getting the proper publicKeyToken for it?
SoaperGEM
Look in the Manifests directory I mentioned earlier for the specific manifest you need.
Vinay Sajip
A: 

Your question was: How do I debug py2exe

Here is a tip:

  • Use dependency walker: www.dependencywalker.com (one day I'll be cool enough to post two URLs)

As for your specific problem, I expect that you will find a solution on this more complete thread dealing with the same problem:

http://stackoverflow.com/questions/323424

resplin