2

我想在 OSX 上(使用 py2app)和 Debian 包分发我的应用程序。

我的应用程序的结构如下:

app/
     debian/
            <lots of debian related stuff>
     scripts/
             app
     app/
         __init__.py
         app.py
         mod1/
              __init__.py
              a.py
         mod2/
              __init__.py
              b.py

我的 setup.py 看起来像:

from setuptools import setup
import os
import os.path

osname = os.uname()[0]

if osname == 'Darwin':
    APP = ['app/app.py']
    DATA_FILES = []
    OPTIONS = {'argv_emulation': True}

    setup(
        app=APP,
        data_files=DATA_FILES,
        options={'py2app': OPTIONS},
        setup_requires=['py2app'],
    )
elif osname == 'Linux':
        setup(
        name = "app",
        version = "0.0.1",
        description = "foo bar",
        packages = ["app", "app.mod1", "app.mod2"],
        scripts = ["scripts/app"],
        data_files = [
            ("/usr/bin", ["scripts/app"]),
       ]
    )

然后,在 b.py (这是在 OSX 上):

from app.mod2.b import *

我得到:

ImportError: No module named mod2.b

所以基本上,mod2 无法访问 mod1。在 Linux 上没有问题,因为 python 模块 'app' 全局安装在 /usr/shared/pyshared 中。但在 OSX 上,该应用程序显然是由 py2app 构建的独立 .app 东西。我想知道我是否完全错误地处理了这个问题,在 OSX 上分发 Python 应用程序时是否有任何最佳实践?

编辑:我也在 b.py 中尝试过这样的 hack:

from ..mod2.b import *

ValueError: Attempted relative import beyond toplevel package

Edit2:似乎与这个如何在 Python 中进行相对导入有关?

4

1 回答 1

5

我不确定这是否是“最佳实践”(我没有将很多 python 软件放入适当的分发中),但我会确保顶级应用程序包位于sys.path. 类似于将以下内容放入顶层__init__.py

try:
    import myapp
except ImportError:
    import sys
    from os.path import abspath, dirname, split
    parent_dir = split(dirname(abspath(__file__)))[0]
    sys.path.append(parent_dir)

我认为这应该以跨平台的方式做正确的事情。

编辑:正如 kaizer.se 指出的那样,这可能在文件中不起作用__init__.py,具体取决于您调用的代码是如何执行的。它仅在评估该文件时才有效。关键是要确保顶层包sys.path来自一些实际运行的代码。

很多时候,为了让我直接在一个包中执行单个文件(为了使用if __name__ eq '__main__'成语进行测试),我会做一些类似放置语句的事情:

import _setup

在有问题的单个文件的顶部,然后创建一个_setup.py根据需要执行路径修改的文件。所以,像:

package/
    __init__.py
    _setup.py
    mod1/
        __init__.py
        _setup.py
        somemodule.py

如果您import _setup来自,则该安装文件可以确保在评估其余代码之前,somemodule.py顶级包就在其中。sys.pathsomemodule.py

于 2009-11-06T15:34:59.407 回答