2009-11-06 161 views
2

我想分发我的应用程序在OSX(使用py2app)和Debian软件包。Python应用程序分发跨平台

我的应用程序的结构是这样的:

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:

from ..mod2.b import * 

ValueError: Attempted relative import beyond toplevel package 

EDIT2:似乎与此有关How to do relative imports in Python?

回答

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 _setupsomemodule.py,该安装文件可以确保顶层包在sys.path代码的somemodule.py其余的评估之前。

+0

这可以解决吗?如果应用程序不在路径中,应用程序如何首先到达程序包的__init__模块? – u0b34a0f6ae