以下の階層では、以下のすべての.pyファイルで一般的な用語を使用してtop_packageを参照するための便利で普遍的な方法はありますか? 「top_package」の名前が変更されても何も壊れないように、他のモジュールをインポートするための一貫した方法が必要です。
相対パスは以下の各pythonファイル。
パッケージ内の.pyファイル内の「top_package」へのデカップリング参照。したがって、「top_package」という名前がどのように変更されても、何も壊れません。
top_package/
__init__.py
level_one_a/
__init__.py
my_lib.py
level_two/
__init__.py
hello_world.py
level_one_b/
__init__.py
my_lib.py
main.py
これでうまくいくはずです:
top_package = __import__(__name__.split('.')[0])
ここでの秘訣は、すべてのモジュールについて、__name__
変数に、たとえばtop_package.level_one_a.my_lib
などのドットで区切られたモジュールへのフルパスが含まれていることです。したがって、最上位のパッケージ名を取得する場合は、パスの最初のコンポーネントを取得し、__import__
を使用してインポートする必要があります。
パッケージへのアクセスに使用される変数名はまだtop_package
と呼ばれていますが、パッケージの名前を変更でき、それでも機能するかどうかを確認できます。
パッケージとmain
スクリプトを次のように外部コンテナディレクトリに配置します。
container/
main.py
top_package/
__init__.py
level_one_a/
__init__.py
my_lib.py
level_two/
__init__.py
hello_world.py
level_one_b/
__init__.py
my_lib.py
main.py
が実行されると、その親ディレクトリ(container
)がsys.path
の先頭に自動的に追加されます。また、top_package
は同じディレクトリにあるため、パッケージツリー内のどこからでもインポートできます。
したがって、hello_world.py
は次のようにlevel_one_b/my_lib.py
をインポートできます。
from top_package.level_one_b import my_lib
コンテナディレクトリの名前や場所に関係なく、インポートは常にこの配置で機能します。
ただし、元の例では、top_package
はコンテナディレクトリ自体として簡単に機能する可能性があることに注意してください。 top_package/__init__.py
を削除するだけで、効果的に同じ配置が残ります。
前のインポートステートメントは次のように変更されます。
from level_one_b import my_lib
top_package
の名前は自由に変更できます。
パッケージの __import__()
関数と __path__
属性の組み合わせを使用できます。
たとえば、パッケージ内の別の場所から<whatever>.level_one_a.level_two.hello_world
をインポートするとします。あなたはこのようなことをすることができます:
import os
_temp = __import__(__path__[0].split(os.sep)[0] + ".level_one_a.level_two.hello_world")
my_hello_world = _temp.level_one_a.level_two.hello_world
このコードはトップレベルパッケージの名前に依存せず、パッケージ内のどこでも使用できます。それもかなり醜いです。
これは、ライブラリモジュール内から機能します。
import __main__ as main_package
TOP_PACKAGE = main_package.__package__.split('.')[0]
相対的なインポートまたは名前付きパッケージを使用しないと、#2は不可能だと思います。名前を明示的に呼び出すか、相対インポートを使用して、インポートするモジュールを指定する必要があります。そうでなければ、通訳はあなたが何を望んでいるのかをどうやって知るのでしょうか?
アプリケーションランチャーをtop_level/
の1レベル上に作成し、それをimport top_leve
lにすると、top_levelパッケージ内のどこからでもtop_level.*
を参照できます。
(私が取り組んでいるソフトウェアの例をお見せできます: http://github.com/toddself/beerlog/ )