PYTHONPATH にパッチを適用して現在のディレクトリを追加するデコレーターを使用して、初期化モジュール内に関数呼び出しをラップします。これにより、パッケージを PYTHONPATH に明示的に追加することを心配することなく、モジュール内で相対インポートを使用できます (@abarnert のコメントに基づいて編集)。
def patch_python_path(f):
@wraps(f)
def wrap(*args, **kwargs):
ROOT = os.pathsep.join([os.path.abspath(os.path.dirname(__file__))])
if not os.environ.has_key("PYTHONPATH"):
os.environ["PYTHONPATH"] = ""
if not (ROOT in os.environ["PYTHONPATH"].split(":")):
os.environ["PYTHONPATH"] = "%s:%s" % (os.environ["PYTHONPATH"], ROOT)
if not ROOT in sys.path:
sys.path.append(ROOT)
return f(*args, **kwargs)
return wrap
使用方法は次のとおりです。
@patch_python_path
def initialize():
#at this point any code being run has access to local modules through relative imports
pass
このアプローチには、私が気付いていない大きな問題はありますか?
これに関する私の目的は次のとおりです。
- ユーザーが追加の環境操作なしですぐに使用できる自己完結型のブートストラップが必要です
- また、ユーザーがブートストラップ パッケージの名前を変更できると想定しているため、すべてのインポートが相対的なままであることが不可欠です。
[編集] 私が直面している問題は、純粋な Python モジュールのインポートとは対照的に、Fabric がタスクを実行する方法に関係していることを実際に認識しています。(fab task1 とは対照的に) Python シェルからタスクを実行しようとすると、パッチを適用する必要なく、すべてのインポートが正しく解決されます。fab を介してタスクを実行するとインポート エラーが発生する