Python(v2.7)のインポートメカニズムに関するベストプラクティスを理解しようとしています。私は少し成長し始めたプロジェクトがあり、私のコードは次のように構成されていると言えます:
foo/
__init__.py
Foo.py
module1.py
module2.py
module3.py
パッケージ名はfoo
であり、その下にクラスFoo
のコードを含むモジュールFoo.py
があります。したがって、パッケージ、モジュール、およびクラスに同じ名前を使用していますが、最初はあまり賢くないかもしれません。
__init__.py
は空であり、クラスFoo
はmodule1, module2 and module3
をインポートする必要があるため、Foo.py
ファイルの一部は次のようになります。
# foo/Foo.py
import module1
import module2
import module3
class Foo(object):
def __init__(self):
....
....
if __name__ == '__main__':
foo_obj = Foo()
しかし、後でこれを再検討し、すべてのインポートを__init__.py
ファイルに含める方が良いと考えました。したがって、私の__init__.py
は次のようになります。
# foo/__init__.py
import Foo
import module1
import module2
import module3
....
....
そして、私のFoo.py
はfoo
のみをインポートする必要があります:
# foo/Foo.py
import foo
これは1つのライナーなので便利に見えますが、循環インポートを作成しているのではないかと少し心配しています。つまり、スクリプトFoo.py
が実行されると、可能な限りすべてがインポートされ、__init__.py
が呼び出され、Foo.py
が再度インポートされます(正しいですか?)。さらに、パッケージ、モジュール、およびクラスに同じ名前を使用すると、事態がさらに混乱します。
それは私がそれをやった方法で理にかなっていますか?または私はトラブルを求めていますか?
PEP 0008、「パブリックおよび内部インターフェース」 :
インポートされた名前は、常に実装の詳細と見なされる必要があります。他のモジュールは、os.pathやサブモジュールから機能を公開するパッケージの
__init__
モジュールなど、含まれるモジュールのAPIの明示的に文書化された部分でない限り、そのようなインポートされた名前への間接アクセスに依存してはなりません。
したがって、これは、__init__
がサブモジュールから関数を公開するために使用されている場合、__init__
モジュールにインポートを置くことはisであることを示唆します。 Here は、__init__
のPythonの使用例をいくつか紹介した短いブログ投稿です。インポートを使用して、パッケージレベルでサブパッケージを使用可能にします。
Foo
にインポートを1つだけにするためにインポートステートメントを__init__
に移動する例は、notこのルールに従ってください。私の解釈では、__init__
のインポートはexternalインターフェイスに使用する必要があります。そうでない場合は、インポートステートメントをそれらを必要とするファイルに入れるだけです。これにより、サブモジュール名が変更された場合のトラブルが軽減され、サブモジュールの異なるサブセットを使用するファイルを追加するときに、不要なインポートや見つけにくいインポートが発生しなくなります。
循環参照に関しては、これはPython( たとえば )で間違いなく可能です。実際にあなたのおもちゃの例を試す前にそれについて書きましたが、例を作るためにFoo.py
を1レベル上げる必要がありました。
Foo.py
foo/
__init__.py
module1.py
module2.py
module3.py
そのセットアップといくつかのprintステートメントで、python Foo.py
を実行すると出力が得られます:
module 1
module 2
module 3
hello Foo constructor
そして正常に終了します。これはif __name__ == "__main__"
を追加することに起因することに注意してください-それ以外にprintステートメントを追加すると、Pythonはまだモジュールを2回ロードしています。より良い解決策は__init__.py
からインポートを削除します。前述したように、これらのサブモジュールが何であるかに応じて、それは意味をなさない場合があります。
ベストプラクティスについては、「Python Code」のスタイルガイド」を参照してください。インポートはそのガイドのクラスに保持されます。
これを試して:
package1.py
__init__.py
test.py
class abc:
a = 'hello'
def print_a(self):
print(a)
from .package1 import abc
From package1.package1 import abc
これらの__init__.pyを使用して、パッケージからインポートします。
これが正しい方法であるかどうかを明確に述べることはできませんが、常に前者の方法で行ってきました。つまり、私は常に__init__.py
を空にしておき、必要に応じてFoo.py
内にインポートしました。
あなたがそれをどのように説明するかから、後者の形でいくつかの循環論理が起こっているように見えます。