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で次のようなハックも試しました:

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 に答える