相互または循環(循環)インポートを使用するとどうなりますか? 質問する

相互または循環(循環)インポートを使用するとどうなりますか? 質問する

Python では、2 つのモジュールがimport相互に試行すると何が起こりますか? より一般的には、複数のモジュールがimport循環的に試行すると何が起こりますか?


参照「ImportError: 名前 X をインポートできません」または「AttributeError: ... (おそらく循環インポートが原因)」についてはどうすればいいですか?起こり得る一般的な問題と、そのようなインポートを回避するためにコードを書き直す方法に関するアドバイスについては、循環インポートはコールスタックの上のほうでは機能しているように見えるのに、下のほうでは ImportError を発生させるのはなぜでしょうか?問題が発生する理由と仕組みに関する技術的な詳細については、

ベストアンサー1

import foo(inside bar.py) とimport bar(inside )を実行するとfoo.py、正常に動作します。実際に何かが実行される頃には、両方のモジュールが完全にロードされ、相互に参照されるようになります。

問題は、代わりにfrom foo import abc(inside bar.py) とfrom bar import xyz(inside foo.py) を実行する場合です。なぜなら、各モジュールをインポートする前に、他のモジュールが既にインポートされている (つまり、インポートする名前が存在する) 必要があるためです。

Python 2 と Python 3 での循環インポートの動作例

記事Python の循環インポートが致命的となるのはどのような場合ですか?循環インポートが、上で説明した理由により致命的ではない場合の例を 4 つ示します。

モジュールの先頭; from なし; Python 2 のみ

# lib/foo.py                         # lib/bar.py
import bar                           import foo

def abc():                           def xyz():
    print(bar.xyz.__name__)              print(foo.abc.__name__)

モジュールの先頭; from ok; relative ok; Python 3 のみ

# lib/foo.py                         # lib/bar.py
from . import bar                    from . import foo

def abc():                           def xyz():
    print(bar.xyz.__name__)              print(abc.__name__)

モジュールの先頭。from なし。相対なし

# lib/foo.py                         # lib/bar.py
import lib.bar                       import lib.foo

def abc():                           def xyz():
    print(lib.bar.xyz.__name__)          print(lib.foo.abc.__name__)

モジュールの下部; モジュールではなく属性をインポート; 正常から

# lib/foo.py                         # lib/bar.py
def abc():                           def xyz():
    print(xyz.__name__)                  print(abc.__name__)


from .bar import xyz                 from .foo import abc

関数の先頭; OKから

# lib/foo.py                         # lib/bar.py
def abc():                           def xyz():
    from . import bar                    from . import foo
    print(bar.xyz.__name__)              print(foo.abc.__name__)

追加の例

上記の記事では、スターの輸入については説明されていません。

おすすめ記事