1

重複の可能性:
Pythonでの巡回加群の依存関係と相対的なインポート

Pythonでの循環インポートの次の例を考えてみましょう。

main.py:

from pkg import foo

pkg / __ init.py__:

# empty

pkg / foo.py:

from pkg import bar

pkg / bar.py:

from pkg import foo

main.pyを実行すると、例外が発生します。

Traceback (most recent call last):
  File "/path/to/main.py", line 1, in <module>
    from pkg import foo
  File "/path/to/pkg/foo.py", line 1, in <module>
    from pkg import bar
  File "/path/to/pkg/bar.py", line 1, in <module>
    from pkg import foo
ImportError: cannot import name foo

bar.pyを次のように変更します。

# from pkg import foo
import pkg.foo 

例が機能します。

なぜこれが起こるのですか?* importpackage.module"と"frompackage import module "は同等ではありませんか(後者の余分な名前バインディングを除く)?

4

1 に答える 1

2

まず第一に、あなたはそれを理解する必要があります:

  • 変数はインポートメカニズムでキャッシュの役割を果たします。sys.modulesつまり、モジュールを最初にインポートすると、このモジュールの名前を含むエントリがに追加されるsys.modulesため、次回この同じモジュールをインポートしようとすると、はすでにキャッシュされたモジュールのみを取得しsys.modules、モジュールを再度実行することはありません。

  • import pkg.fooとの違いfrom pkg import fooは、2番目も同等であるということです。import pkg.fooその後に。が続きgetattr(pkg, 'foo')ます。(詳細については、ここで私の答えを確認してください)

最初の例で何が起こるかは次のとおりです。

1- In main.py:行を実行することから始めます。したがって、インポートしようとするよりもfrom pkg import foo、最初にエントリが(つまり)pkg.fooに追加されます。sys.modules'pkg.foo' in sys.modules == Truefoo

2- In foo.py:インポートfoo中に、この行を実行することになります:from pkg import barそして再びエントリが;pkg.barに追加されます。sys.modulesインポートを開始するよりもbar、ここで重要なのは、まだ実行中であるということです。したがって、からfoo.pyこの行を実行しているのは親切です。from pkg import foomain.py

3- In bar.py:インポートbar.py中に、次の行を実行することになります: 、ただし、実行がスキップされ、インポートmechanizeが代わりにエントリを取得することを意味するfrom pkg import fooエントリがすでにあることを覚えておいてください。次に、上記で説明したように実行します。 、ただし、「pkg.foo」のインポートが完了しなかったことを覚えておいてください。これは、エラーを説明する属性がないことを意味します。sys.modulespkg.foofoo.pysys.modules['pkg.foo']getattr(pkg, 'foo')foo

bar.pyさて、これだけを入れると、import pkg.foo前回問題を引き起こした行はありません:getattr(pkg, 'foo')

HTH、

于 2012-09-08T14:06:11.743 に答える