パッケージの階層を持つアプリケーションがあります。パッケージ階層の上位にある他のモジュールを参照するモジュールはかなりの数あります。以下に例示するように、相対インポートを使用してこの問題を解決できます。ただし、テストのためにモジュールを直接実行すると、Attempted relative import in non-package
例外が発生して失敗します。
モジュールをテスト用に個別に実行し、他のモジュールからインポートできるように、アプリケーションまたはインポートステートメントを整理するためのより良い方法はありますか?
例
\spam
\morespam
child.py
base.py
\eggs
user.py
base.py
class Base(object):
def hello(self):
print 'Um, wot?'
child.py
from ..base import Base # references the parent package correctly,
# but fails when this module is executed individually
class Child(Base):
def hello(self):
print 'Hello, world!'
if __name__ == '__main__':
import unittest
# ... unit test code ...
user.py
from spam.morespam.child import Child
print Child().hello()
既存のソリューション
階層の上位にあるモジュールを参照する必要があるモジュールの先頭に、次のヘッダーを追加できることがわかりました。
if __name__ == '__main__':
import sys, os
sys.path.append(os.path.abspath(os.path.join(sys.path[0], '..')))
欠点は、このコードをあちこちに追加する必要があることです。これは一定ではありません。'..'
相対パスは、階層内のパッケージの深さによって異なります。
他の可能な解決策...
- アプリケーションルートを使用して.pthファイルを作成できます。残念ながら、これはPythonインストールのsite-packagesフォルダーに追加する必要があるため、アプリケーション固有ではありません。
- アプリケーションルートを一時的にPYTHONPATHに追加し、すべてのモジュールがルートからパッケージを参照するようにすることができます。ただし、これにより、を呼び出すだけでスクリプトを実行するという単純さがなくなり
python.exe whatever.py
ます。 - インポートすると、アプリケーションのルートフォルダーでマーカーファイルを検索するようなモジュールを作成できます。次に、この汎用モジュールをローカルのPythonインストールにインストールして、アプリ内のすべてのモジュールにインポートできるため、実行しているモジュールに関係なく、ルートがPYTHONPATHにあることが保証されます。