479

2 つのモジュールが相互にインポートするとどうなりますか?

問題を一般化すると、Python の循環インポートはどうなるでしょうか?

4

13 に答える 13

402

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

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

于 2009-04-14T02:03:43.453 に答える
338

昨年、 comp.lang.pythonでこれについて本当に良い議論がありました。それはあなたの質問にかなり徹底的に答えます。

インポートは非​​常に簡単です。次のことを覚えておいてください。

'import'および'fromxxximportyyy'は実行可能ステートメントです。実行中のプログラムがその行に到達すると実行されます。

モジュールがsys.modulesにない場合、インポートによってsys.modulesに新しいモジュールエントリが作成され、モジュール内のコードが実行されます。実行が完了するまで、呼び出し元のモジュールに制御を戻しません。

モジュールがsys.modulesに存在する場合、インポートは、実行が完了したかどうかに関係なく、そのモジュールを返すだけです。これが、循環インポートが部分的に空のように見えるモジュールを返す場合がある理由です。

最後に、実行中のスクリプトは__main__という名前のモジュールで実行され、独自の名前でスクリプトをインポートすると、__main__とは関係のない新しいモジュールが作成されます。

その多くをまとめると、モジュールをインポートするときに驚くことはありません。

于 2009-04-13T16:15:00.700 に答える
117

循環インポートは終了しますが、モジュールの初期化中に循環インポートされたモジュールを使用しないように注意する必要があります。

次のファイルを検討してください。

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れます。aAttributeError

次の行をに追加します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ます。

于 2009-04-13T16:16:23.973 に答える
12

ここで私を驚かせた例を手に入れました!

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
于 2009-04-14T07:30:51.730 に答える
0

わかりました、かなりクールな解決策があると思います。fileaと fileがあるとしますb。module で使用したいファイル内defまたはがありますが、 file内の定義またはクラスで必要なfile からの、、または変数のいずれかがあります。あなたができることは、 file の最後で、 fileに必要なfile の関数またはクラスを呼び出した後、 fileに必要な file から関数またはクラスを呼び出す前に、次のように言うことです。 ここに重要な部分があります、またはfrom fileを必要とするファイル内のすべての定義またはクラスclassbadefclassabaabbaimport bbdefclassa(それを と呼びましょうCLASS)、あなたは言うfrom a import CLASS

これbは、Python が file 内の import ステートメントを実行せずにfile をインポートできるためb、循環インポートを回避できるため機能します。

例えば:

ファイル a:

class A(object):

     def __init__(self, name):

         self.name = name

CLASS = A("me")

import b

go = B(6)

go.dostuff

ファイル b:

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."

出来上がり。

于 2015-02-06T01:07:27.257 に答える