py2exe doesn't find all dependencies

Doo Dah picture Doo Dah · Mar 18, 2013 · Viewed 8.8k times · Source

I am trying to create an exe from python code. I can run the code just fine from the command line like this:

python myScript.py

I have installed py2exe from here: http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/

And, have a setup.py that looks like this:

from distutils.core import setup
import py2exe

setup(console=['myScript.py'])

And, I run the setup.py like this:

python setup.py py2exe

I get the following in the output:

The following modules appear to be missing
['Carbon', 'Carbon.Files', '__pypy__', '_scproxy', 'http_parser.http', 'http_parser.reader', 'jinja2._debugsupport', 'jinja2._markupsafe._speedups',
'jinja2.debugrenderer', 'markupsafe', 'pretty', 'socketpool', 'socketpool.util']

And, sure enough, if I try to run the exe, I get errors:

$ ./myScript.exe
Traceback (most recent call last):
  File "restkit\__init__.pyc", line 9, in <module>
  File "restkit\conn.pyc", line 14, in <module>
ImportError: No module named socketpool
Traceback (most recent call last):
  File "myScript.py", line 12, in <module>
ImportError: cannot import name Resource

What do I need to do to get py2exe to find the dependencies?

Thanks

Answer

abarnert picture abarnert · Mar 18, 2013

Carbon is the name of two different Mac-specific things.

First, in 2.x, on both Mac OS X and Mac Classic builds, has a Carbon package in the standard library, used for calling Carbon/Toolbox APIs (and, in OS X, CoreFoundation and friends).

Second, in both 2.x and 3.x, on Mac OS X, with PyObjC, the PyObjC wrapper around Carbon.Framework is named Carbon. (PyObjC isn't part of the stdlib, but it does come with Apple builds of Python, and most third-party builds besides python.org's official installers.)

Neither of these will exist on Windows.

py2exe tries to be smart and only import things relevant to your platform. However, it's pretty easy to fool. For example, something like this:

try:
    import Carbon.Files
except:
    Carbon = collections.namedtuple('Carbon', 'Files')
    Carbon.Files = None

if Carbon.Files:
    Carbon.Files.whatever(…)

… might make py2exe think Carbon.Files is required.

Now, obviously this isn't your whole problem, but it is a very big red flag that py2exe's module dependency code is not working for your project. You probably have similar problems with all kinds of other modules, so it's both missing some things you need and demanding some things you don't have, and this is probably what's causing your actual problems.

As the FAQ explains, you can debug this by running the module-finder code to see where it's going wrong, like this:

python -m py2exe.mf -d path/to/my_file.py

You could use this information to guide the module-finder code, or to rewrite your code so you don't confuse py2exe.

Or, more simply, just explicitly include and exclude modules in your setup.py as a workaround, without worrying about why they're getting incorrectly detected.