我有一个Python应用程序,可以在运行时动态加载python模块(使用__import__
)。要加载的模块位于名为“plugins
”的包中(即名为plugins
的子文件夹,其中包含__init__.py
等)。所有工作从python解释器运行良好,甚至使用py2exe编译为Windows二进制文件。
我尝试从中构建一个OSX应用程序,但是在运行.app时我得到了一个ImportError:'no module named plugins.xxxx
'。
我很确定我为py2app('includes': [...]
,'packages':['plugins']
提供了正确的选项,与我为py2exe所做的相同),因为当我浏览.app内容时,我看到了所有的插件文件夹Contents/Resources/lib/python2.5/plugins/
中的模块。
那么,为什么app不能找到我的模块(必须是一些路径问题)?
修改
我找到了一种方法让它起作用,但这不是一个好的解决方案:
当我打印Python搜索模块的路径时(使用print sys.path
),我注意到未列出文件夹Contents/Resources/lib/python2.5/plugins/
。但是,文件夹Contents/Resources/
是,因此我将plugins
文件夹移动到Contents/Resources
文件夹。现在找到了插件。但是我对这个丑陋的手动黑客仍然不满意。
答案 0 :(得分:0)
Koo使用以下代码。您可能需要执行类似的操作以检测您是否在py2app中,并相应地调整导入。
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] )