Getting py2exe to work with zope.interface

10,513

Solution 1

I've had this same problem with zope.interface and friends (zope.component, et al). Specifically it is a problem with how py2exe searches and discovers packages AND how the zope packages are installed.

zope is a namespace package and as a result relies on some funky import logic in it's .pth files (see zope.interface-3.*.*-py2.*-nspkg.pth) in order to add it's sub-packages to python's path. Have a look at it in site-packages and you'll see what I mean.

py2exe has problems "discovering" this kind of package.

In the end what I did was manually repackage the various zope packages I was using into a stardard module setup in site-packages and then reran py2exe - which then discovered everything no problem. It's a PITA, but until py2exe is able to handle packaging edge cases and/or the zope packages are packaged in a py2exe friendly fashion, it's about the best you can do.

Solution 2

I don't know if you ever solved this, or if it's even relevant to you anymore, but for future searchers, I found an easy way to fix the zope import problem here.

Specifically, add an empty __init__.py file to the PYTHONDIR/Lib/site-packages/zope directory.

I tested this with a twisted application, using this setup file:

#!/usr/bin/env python
'''
File: setup.py
Author: Spencer Rathbun
Date: 07/24/2012
Description: Setup file for py2exe, converts client python script into executable.
'''
from distutils.core import setup
import py2exe

INCLUDES = [
    ''
]

PACKAGES = [
    'twisted'
]

setup(
        name = 'client',
        description = '',
        version = '1.0',

        console = [
            {"script":"client.py",
                "icon_resources":[
                    (1, "c:\python27\DLLs\py.ico")
                    ]
                }
            ],
        zipfile = None,

        options = {"py2exe":
            {"compressed": 1,
                "optimize": 1,
                "ascii": 0,
                "bundle_files": 1,

                "packages": ','.join(PACKAGES),
                "includes": ','.join(INCLUDES),
                }
            }
        )

Py2exe can use this to successfully create an executable for twisted now, since it depends upon zope.

Solution 3

I was facing this issue in creating a package using py2exe in Windows XP SP3. I figured out that py2exe was not determining the dependencies correctly.

To solve this issue, I uninstalled my third party package(s) and installed them using following easy_install command

easy_install -Z <your_package_name>

The -Z option unzips the package details, and hence the content is not compressed. When you run py2exe now, it will correctly detect the dependencies.

Hope this helps!

Share:
10,513
detly
Author by

detly

Updated on June 04, 2022

Comments

  • detly
    detly almost 2 years

    I have a Python app based on Twisted and PyGTK. Twisted itself depends on zope.interface, and I don't import it directly.

    Unfortunately, when I try to run my app, the following error ends up in the error log:

    Traceback (most recent call last):
      File "tasks.py", line 4, in <module>
      File "ui\__init__.pyc", line 14, in <module>
      File "twisted\python\log.pyc", line 17, in <module>
    ImportError: No module named zope.interface
    Traceback (most recent call last):
      File "tasks.py", line 4, in <module>
      File "ui\__init__.pyc", line 14, in <module>
      File "twisted\python\log.pyc", line 17, in <module>
    ImportError: No module named zope.interface
    Traceback (most recent call last):
      File "tasks.py", line 4, in <module>
      File "ui\__init__.pyc", line 14, in <module>
      File "twisted\python\log.pyc", line 17, in <module>
    ImportError: No module named zope.interface
    

    I've tried adding every combination of zope.interface and zope to INCLUDES and PACKAGES, but doing so only gives me this build time error:

    running py2exe
    *** searching for required modules ***
    C:\Python26\lib\site-packages\py2exe\build_exe.py:16: DeprecationWarning: the sets module is deprecated
      import sets
    Traceback (most recent call last):
      File "setup.py", line 75, in <module>
        'gtk/*.ui'
      File "C:\Python26\lib\distutils\core.py", line 152, in setup
        dist.run_commands()
      File "C:\Python26\lib\distutils\dist.py", line 975, in run_commands
        self.run_command(cmd)
      File "C:\Python26\lib\distutils\dist.py", line 995, in run_command
        cmd_obj.run()
      File "C:\Python26\lib\site-packages\py2exe\build_exe.py", line 243, in run
        self._run()
      File "C:\Python26\lib\site-packages\py2exe\build_exe.py", line 296, in _run
        self.find_needed_modules(mf, required_files, required_modules)
      File "C:\Python26\lib\site-packages\py2exe\build_exe.py", line 1306, in find_needed_modules
        mf.import_hook(f)
      File "C:\Python26\lib\site-packages\py2exe\mf.py", line 719, in import_hook
        return Base.import_hook(self,name,caller,fromlist,level)
      File "C:\Python26\lib\site-packages\py2exe\mf.py", line 136, in import_hook
        q, tail = self.find_head_package(parent, name)
      File "C:\Python26\lib\site-packages\py2exe\mf.py", line 204, in find_head_package
        raise ImportError, "No module named " + qname
    ImportError: No module named zope
    

    My setup.py is:

    from distutils.core import setup
    import py2exe
    
    def find_data_files(source,target,patterns):
        # I've elided this, I doubt it's relevant to the problem
        # ...
    
    INCLUDES = [
        'cairo',
        'pango',
        'pangocairo',
        'atk',
        'gobject',
        'gio',
    ]
    
    PACKAGES = [
        'encodings',
    ]
    
    setup(
        name = 'MyApp',
        description = 'My Application',
        version = '1.0',
    
        windows = [
                      {
                          'script': os.path.join('ui','tasks.py'),
                          'icon_resources': [
                                (1, os.path.join(
                                    'ui','data','iconpack.ico'))
                            ],
                      }
                  ],
    
        options = {
                      'py2exe': {
                          'packages': ','.join(PACKAGES),
                          'includes': ','.join(INCLUDES),
                      }
                  },
    
        data_files = find_data_files(
                        'ui', 'ui', [
                            'data/*',
                            'gtk/*.ui'
                        ])
    
    )
    

    How do I get py2exe to build this?

  • detly
    detly over 12 years
    I went to check that I could do this without running afoul of their license. Is it just me, or is the Zope Public License not actually included with any of their distributions?
  • Mark Gemmill
    Mark Gemmill over 12 years
    There is a reference to the license include at the top of the actual code files - which is all they need. You are not doing anything contrary to the license (i.e. you are not actually changing the code in any way), you're just altering how the package is installed on your system. It's not any different than what py2exe already does with all your python libraries it packs into an exe.
  • detly
    detly over 12 years
    Bah, here it is.
  • detly
    detly over 12 years
    my impression is that it'd still be creating a derived work, but it looks like the license is fairly liberal about that anyway, so no matter.
  • detly
    detly over 12 years
    Okay, I'm marking this as the answer, since it got me past this phase, but now py2exe is choking on pretty much every other package I use so I'm abandoning it. So for anyone else reading this, I have no way to verify whether it worked in the final built executable :/
  • Mark Gemmill
    Mark Gemmill over 12 years
    ah, yeah, py2exe takes a bit of work sometimes to get all the various packages to bundle. Usually py2exe is pretty good at letting you know which libraries it has trouble with, but some (like zope) take some investigation. There are a number of tips, etc. on the py2exe website, but its a bit disorganized and takes a bit of digging. I've packaged an app with wxPython, zope, and a few others and it took me several painful days to sort through the problem. Once it was done, everything worked nicely. Getting there is just a PITA.
  • detly
    detly over 12 years
    Yeah, maybe I just need to stick with it. I get the feeling it's not going to be easier with any other system.
  • Adam Nemitoff
    Adam Nemitoff about 10 years
    Having to repackage can be avoided by using Spencer's really simple answer below.
  • Willem D'Haeseleer
    Willem D'Haeseleer almost 10 years
    This worked for me, should be the accepted answer imo
  • Bjorn Stiel
    Bjorn Stiel almost 9 years
    Yep, this is by far the best answer. thanks for that
  • digitalacorn
    digitalacorn over 8 years
    Yes, worked for me with the repoze (repoze.lru) module required by the routes module.