2 つのモジュールが相互にインポートするとどうなりますか?
問題を一般化すると、Python の循環インポートはどうなるでしょうか?
2 つのモジュールが相互にインポートするとどうなりますか?
問題を一般化すると、Python の循環インポートはどうなるでしょうか?
import foo
(inside bar.py
) とimport bar
(inside )を実行foo.py
すると、正常に動作します。何かが実際に実行されるまでに、両方のモジュールが完全にロードされ、相互に参照されます。
問題は、代わりにfrom foo import abc
(inside bar.py
) とfrom bar import xyz
(inside ) を実行する場合ですfoo.py
。各モジュールは、インポートする前に (インポートする名前が存在するように) 他のモジュールが既にインポートされている必要があるためです。
昨年、 comp.lang.pythonでこれについて本当に良い議論がありました。それはあなたの質問にかなり徹底的に答えます。
インポートは非常に簡単です。次のことを覚えておいてください。
'import'および'fromxxximportyyy'は実行可能ステートメントです。実行中のプログラムがその行に到達すると実行されます。
モジュールがsys.modulesにない場合、インポートによってsys.modulesに新しいモジュールエントリが作成され、モジュール内のコードが実行されます。実行が完了するまで、呼び出し元のモジュールに制御を戻しません。
モジュールがsys.modulesに存在する場合、インポートは、実行が完了したかどうかに関係なく、そのモジュールを返すだけです。これが、循環インポートが部分的に空のように見えるモジュールを返す場合がある理由です。
最後に、実行中のスクリプトは__main__という名前のモジュールで実行され、独自の名前でスクリプトをインポートすると、__main__とは関係のない新しいモジュールが作成されます。
その多くをまとめると、モジュールをインポートするときに驚くことはありません。
循環インポートは終了しますが、モジュールの初期化中に循環インポートされたモジュールを使用しないように注意する必要があります。
次のファイルを検討してください。
a.py:
print "a in"
import sys
print "b imported: %s" % ("b" in sys.modules, )
import b
print "a out"
b.py:
print "b in"
import a
print "b out"
x = 3
a.pyを実行すると、次のようになります。
$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
b out
a out
b.pyの2番目のインポート(2番目)では、Pythonインタープリターはモジュールdictに既に存在するため、再度a in
インポートされません。b
モジュールの初期化中にからアクセスしようとすると、が表示さb.x
れます。a
AttributeError
次の行をに追加しますa.py
。
print b.x
次に、出力は次のとおりです。
$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
Traceback (most recent call last):
File "a.py", line 4, in <module>
import b
File "/home/shlomme/tmp/x/b.py", line 2, in <module>
import a
File "/home/shlomme/tmp/x/a.py", line 7, in <module>
print b.x
AttributeError: 'module' object has no attribute 'x'
これは、モジュールがインポート時に実行され、b.x
アクセス時にその行x = 3
がまだ実行されていないためです。これは、の後にのみ発生しb out
ます。
ここで私を驚かせた例を手に入れました!
foo.py
import bar
class gX(object):
g = 10
bar.py
from foo import gX
o = gX()
main.py
import foo
import bar
print "all done"
コマンドラインで: $ python main.py
Traceback (most recent call last):
File "m.py", line 1, in <module>
import foo
File "/home/xolve/foo.py", line 1, in <module>
import bar
File "/home/xolve/bar.py", line 1, in <module>
from foo import gX
ImportError: cannot import name gX
わかりました、かなりクールな解決策があると思います。filea
と fileがあるとしますb
。module で使用したいファイル内def
またはがありますが、 file内の定義またはクラスで必要なfile からの、、または変数のいずれかがあります。あなたができることは、 file の最後で、 fileに必要なfile の関数またはクラスを呼び出した後、 fileに必要な file から関数またはクラスを呼び出す前に、次のように言うことです。
ここに重要な部分があります、またはfrom fileを必要とするファイル内のすべての定義またはクラスclass
b
a
def
class
a
b
a
a
b
b
a
import b
b
def
class
a
(それを と呼びましょうCLASS
)、あなたは言うfrom a import CLASS
これb
は、Python が file 内の import ステートメントを実行せずにfile をインポートできるためb
、循環インポートを回避できるため機能します。
例えば:
class A(object):
def __init__(self, name):
self.name = name
CLASS = A("me")
import b
go = B(6)
go.dostuff
class B(object):
def __init__(self, number):
self.number = number
def dostuff(self):
from a import CLASS
print "Hello " + CLASS.name + ", " + str(number) + " is an interesting number."
出来上がり。