Pythonの循環インポート
『初めてのPython』第2版のp.348に載っている循環インポートについて。
解説1回読んだだけじゃよく分からなかったのでめも。
以下の2つのファイルがあったとします。
#recur1.py x = 1 import recur2 y = 2
#recur2.py from recur1 import x from recur2 import y
ここで、対話型コマンドラインで import recur1とすると、
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "recur1.py", line 3, in <module> import recur2 File "recur2.py", line 3, in <module> from recur1 import y ImportError: cannot import name y
とエラーになります。import recur2とした場合にはエラーになりません。
この理由はPythonでは、新たにインポートされたモジュールはコードが実行される前にディクショナリであるsys.modules追加され、2回目以降のインポートではこのディクショナリから値が抽出されるからだそうです。
ちなみに from recur1 import x というのは import recur1; x = recur1.x とほぼ同じだそうで、fromで指定したからといってxが見つかった時点でrecur1の読み込みが終わるという訳ではないみたいです。
対話型コマンドラインでimport recur1とした時
・xに1が代入される
・import recur2 が実行
・recur2内で from recur1 import x が実行
・recur2内で from recur1 import y が実行
・しかしこの時まだyには値が代入されていないのエラー
対話型コマンドラインでimport recur2とした時
・from recur1 import x が実行
・xに1が代入される
・import recur2 が実行される (特定の変数ではなくrecur2というオブジェクト自体をインポート)
・この時すでにsys.modulesにはrecur2が存在するので、recur2は不完全だけれどエラーにはならない
・yに1が代入される
・from recur1 import y が実行
% python recur1.py とした時
・インポートしていないので起動時にsys.modulesにrecur1は追加されていない
・xに1が代入される
・対話型コマンドラインでimport recur2とした時と同じ動作
・→エラーにならない
% python recur2.py とした時
・インポートしていないので起動時にsys.modulesにrecur2は追加されていない
・from recur1 import x が実行
・対話型コマンドラインでimport recur1とした時と同じ動作
・→エラー
ということが行なわれてるってことでいいのかな?