py2app: как включить модули, которые будут загружаться __import__? - PullRequest
2 голосов
/ 20 августа 2010

У меня есть приложение Python, которое динамически загружает модули Python во время выполнения (используя __import__). Загружаемые модули находятся в пакете с именем plugins (т.е. подпапка с именем plugins с __init__.py и т. Д.). Все работает нормально, работает из интерпретатора Python и даже при компиляции в двоичный файл Windows с использованием py2exe.

Я попытался создать приложение OSX из него, но это успешно, но при запуске .app я получаю ImportError: 'no module named plugins.xxxx'.

Я почти уверен, что дал правильные параметры py2app ('includes': [...], 'packages':['plugins'], идентично тому, что я делаю для py2exe), поскольку при просмотре содержимого .app я вижу все модули плагинов в папке Contents/Resources/lib/python2.5/plugins/.

Итак, почему приложение не может найти мои модули (должна быть какая-то проблема с путями)?

Edit:

Я нашел способ заставить его работать, но это не очень хорошее решение: Когда я напечатал пути, которые Python ищет для модулей (используя print sys.path), я заметил, что папка Contents/Resources/lib/python2.5/plugins/ НЕ была указана. Однако папка Contents/Resources/ есть, поэтому я переместил папку plugins в папку Contents/Resources. Теперь плагины найдены. Но я все еще не доволен этим уродливым ручным хакером.

1 Ответ

0 голосов
/ 07 января 2011

Ку использует следующий код. Вероятно, вам нужно будет сделать что-то похожее, чтобы обнаружить, что вы находитесь в py2app, и соответствующим образом настроить свой импорт.

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] )
...