2012-10-11 15 views
9

Pythonでどのように循環インポートが処理されるのか疑問に思っています。私は最小限の質問を掘り下げようとしましたが、私はこの正確な変種が以前に尋ねられたとは思いません。私はlib.foolib.bar間の循環依存を持っている場合基本的に、私はPythonの "import lib.foo"と "import lib.foo f"の相違点

import lib.foo 

import lib.foo as f 

の違いを見ています。私は両方とも同じように動作することを期待していました。(おそらく半初期化された)モジュールはsys.modulesにあり、ローカルの名前空間に入れられます。 (テストから、私はimport lib.fooが本当にローカル名前空間にlibを置くことに気づいた - 。私はとにかくlib.foo.somethingをやるという構文で、大丈夫)

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

また、この動作は文書化されていますか?私はPython import statement referenceがこの動作を説明していると感じていない、または少なくとも私はそれを抽出できませんでした:-)

まったく私はoft recommendedスタイルを使用するようにコードベースを変更しようとしています。モジュールでない記号:

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

しかし、それは二つのモジュール間の循環輸入品がある場合に失敗します。私は、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' 
+0

http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Imports#Importsが破損しています - 読んでいただければ幸いです –

答えて

6

あなたはimport lib.foo as fは何をするのPythonを言っていることは、バイトコードレベルでのimport lib.foo; f = lib.fooのと同等であると言います。この場合のlibにはまだ属性としてfooが設定されていないため、尋ねられている問題でAttributeErrorが発生します。 Pythonは割り当てを試みるときにlib.fooのインポートを完了していないため、属性をまだ設定していませんlib;インポートのためにPython 3.3のソースを見てください。ここでmodule is loadedと対のステートメントがより遠くにある場所を見ることができます。module is set on its parent

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

+0

回答ありがとうございます!したがって、 'lib.foo'をインポートすると' lib'が最初にインポートされ、 'lib.foo'がインポートされると、' lib'に 'foo'属性が設定されます。そのため、 'lib.foo.something'は後で動作します:' lib'パッケージで 'foo' *属性*を見つけます。なぜ' import lib.foo'が 'lib'をローカル名前空間に入れたのかを説明します。 –

+0

はい、それはすべて正しいです。 –

関連する問題