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とした時と同じ動作
・→エラー


ということが行なわれてるってことでいいのかな?