9

Python での循環インポートの処理方法に困惑しています。私は最小限の質問を抽出しようとしましたが、この正確なバリアントが以前に尋ねられたとは思いません. 基本的に、私は違いを見ています

import lib.foo

import lib.foo as f

lib.fooと の間に循環依存関係がある場合lib.bar。どちらも同じように動作することを期待していました。(おそらく半分初期化された) モジュールはsys.modules、ローカル名前空間で検出され、配置されます。import lib.foo(テストから、これが実際にローカル名前空間に配置されていることに気付きlibました — オーケー、lib.foo.somethingとにかくその構文を使用します。)

ただし、lib.fooがすでに にあるsys.modules場合は、 の属性としてimport lib.foo as fアクセスしようとし、AttributeError を発生させます。動作が (一見) の存在に依存するのはなぜですか?foolibsys.modules

また、この動作はどこに文書化されていますか? Pythonimportステートメント リファレンスがこの動作を説明しているとは思わないか、少なくとも抽出できませんでした :-)

全体として、モジュール内のシンボルではなく、モジュールをインポートする推奨されるスタイルを使用するようにコードベースを変更しようとしています。

from project.package import moduleA
from project.package import moduleB

しかし、2 つのモジュール間に循環インポートがあると失敗します。2 つのモジュールの最上位の定義が相互に依存しない限り (たとえば、 にmoduleB基本クラスを持つサブクラスがない場合moduleA)、それが機能することを期待していました。

テスト スクリプト:

#!/bin/sh
rm -r lib; mkdir lib

touch lib/__init__.py

cat > lib/foo.py <<EOF
# lib.foo module
print '{ foo'
#import lib.bar # works
import lib.bar as b # also works
#from lib import bar # also works
print 'foo }'
EOF

cat > lib/bar.py <<EOF
# lib.bar module
print '{ bar'
#import lib.foo # works
import lib.foo as f # AttributeError: 'module' object has no attribute 'foo'
#from lib import foo # ImportError: cannot import name foo
print 'bar }'
EOF

python -c 'import lib.foo'
4

1 に答える 1

6

import lib.foo as fPython に指示していることは、import lib.foo; f = lib.fooバイトコード レベルと同じです。libこの場合、属性としてまだ設定されていないため、質問されている問題で AttributeError になりfooます。lib.fooPython は、割り当てを実行しようとしたときにのインポートを完了していないため、属性をまだ on に設定していませんlib。import の Python 3.3 ソースを見てください。ここでは、モジュールがロードされている場所と、モジュールがその親に設定されている場所のさらに下にあるカップル ステートメントを確認できます。

これは、いくつかの循環インポートの問題が発生する場所です。にアクセスする前にインポートをlib.foo完了する必要がありますlib.foo。そうしないと、バイトコードがアクセスする属性 onlibがまだ存在しません。これが、トップレベルの定義をコードで直接使用していないと思う理由かもしれませんが、実際には import ステートメントを使用しています。

于 2012-10-11T15:17:45.533 に答える