开发者

py2app: how to include modules that will be loaded by __import__?

I have a Python application that loads python modules dynamically at run time (using __import__). The modules to load are in a package called 'plugins' (i.e. subfolder called plugins with __init__.py etc). All works fine running from the python interpreter, and even when compiled to a windows binary using py2exe.

I tried building a OSX app from it, which succeeded, but when running the .app I get an ImportError: 'no module named plugins.xxxx'.

I am pretty sure I gave the correct options to py2app ('includes': [...], 'packages':['plugins'], identical to what I do for py2exe), since when I browse the .app content, I see all the plugin modules in a folder Contents/Resources/lib/python2.5/plugins/.

So, why can't the app find my modules (must be some path issue)?

Edit:

I've found a way to make it work, but it isn't a good solution: When I printed the paths Python searches for modules (using print sys.path), I noticed that the folder开发者_JAVA技巧 Contents/Resources/lib/python2.5/plugins/ was NOT listed. However, the folder Contents/Resources/ is, so I moved the plugins folder to the Contents/Resources folder. Now the plugins are found. But I am still not happy with this ugly, manual hack.


Koo uses the following code. You'll probably need to do something similar to detect that you're in py2app, and adjust your import accordingly.

http://bazaar.launchpad.net/~openobject-client-kde/openobject-client-kde/5.0/annotate/head%3A/Koo/Common/Plugins.py

def scan( module, directory ):
        pluginImports = __import__(module, globals(), locals())
        # Check if it's being run using py2exe or py2app environment
        frozen = getattr(sys, 'frozen', None)
        if frozen == 'macosx_app' or hasattr(pluginImports, '__loader__'):
                # If it's run using py2exe or py2app environment, all files will be in a single 
                # zip file and we can't use listdir() to find all available plugins.
                zipFiles = pluginImports.__loader__._files
                moduleDir = os.sep.join( module.split('.') )
                files = [zipFiles[file][0] for file in zipFiles.keys() if moduleDir in file]
                files = [file for file in files if '__init__.py' in file]
                for file in files:
                        d = os.path.dirname(file)
                        if d.endswith( moduleDir ):
                                continue
                        newModule = os.path.basename(os.path.dirname(file))
                        __import__( '%s.%s' % (module, newModule), globals(), locals(), [newModule] )
        else:
                for i in os.listdir(directory):
                        path = os.path.join( directory, i, '__init__.py' )
                        if os.path.isfile( path ):
                                __import__( '%s.%s' % (module, i), globals(), locals(), [i] )
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜