がabc
パッケージでxyz
あり、がモジュールであり、がを含まないを定義している場合abc
、は__init__.py
実行できませんが、は実行できます。__all__
xyz
from abc import xyz
import abc.xyz
編集:簡単な答えは:あなたの問題はあなたの輸入が循環的であるということです。モジュールtとdは、相互にインポートしようとします。これは機能しません。しないでください。以下で全体を説明しますが、説明はかなり長いです。
ImportErrorが発生する理由を理解するには、コードの実行を追跡してみてください。最後の部分だけでなく、完全なトレースバックを見ると、それが何をしているのかがわかります。あなたのセットアップで私はこのようなトレースバックを取得します(私はパッケージを「コード」ではなく「テストパック」と呼びました):
Traceback (most recent call last):
File "t.py", line 1, in <module>
from testpack import d
File "C:\Documents and Settings\BrenBarn\My Documents\Python\testpack\d.py", line 1, in <module>
from testpack import t
File "C:\Documents and Settings\BrenBarn\My Documents\Python\testpack\t.py", line 1, in <module>
from testpack import d
ImportError: cannot import name d
ここでPythonが何をしているのかを見ることができます。
- ロード
t.py
時に、最初に表示されるのはですfrom testpack import d
。
- その時点で、Pythonは
d.py
ファイルを実行してそのモジュールをロードします。
- しかし、最初に見つかるのはです
from testpack import t
。
- すでに
t.py
一度ロードされていますが、メインスクリプトとしてのtはモジュールとしてのtとは異なるため、t.py
再度ロードを試みます。
- 最初に表示されるのは、です。これは
from testpack import d
、をロードしようとする必要があることを意味しますd.py
。。。しかし、それはすでにステップ2でロードバックを試みていました。インポートしようとすると、再度インポートしようとしたため、Pythonはインポートできないことを認識し、ImportErrorをスローします。d.py
d
d
d
ステップ4は、パッケージ内のファイルを直接実行したため、ここでは一種の異常です。これは、通常の方法ではありません。モジュールのインポートがモジュールの直接実行と異なる理由の説明については、この質問を参照してください。代わりに(を使用して)インポート しようとすると、Pythonは循環性を1ステップ早く認識し、より単純なトレースバックを取得します。t
from testpack import t
>>> from testpack import t
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
from testpack import t
File "C:\Documents and Settings\BrenBarn\My Documents\Python\testpack\t.py", line 1, in <module>
from testpack import d
File "C:\Documents and Settings\BrenBarn\My Documents\Python\testpack\d.py", line 1, in <module>
from testpack import t
ImportError: cannot import name t
ここでのエラーは、tをインポートできないことです。私がtをインポートするように言ったとき、それ自体がループバックしてtを再度インポートすることに気付いたので、それができないことを知っています。元の例では、t.pyが2回実行されていることに気づきませんでした。これは、1回目がメインスクリプトで、2回目がインポートであったため、もう1つの手順を実行して、dを再度インポートしようとしたためです。
さて、あなたがそうするとき、なぜこれは起こらないのimport code.d
ですか?答えは、インポートされたモジュールを実際に使用しようとしないからです。この場合、次のようになります(from code import t
スクリプトとして実行するのではなく、使用したかのように説明します)。
- tのインポートを開始します。これを行うと、
code.t
まだインポートが完了していなくても、モジュールにインポート済みのマークが暫定的に付けられます。
- やらなければならないことがわかった
import code.d
ので、dを実行します。
- dでは、が見つかります
import code.t
が、code.t
すでにインポート済みとしてマークされているため、再度インポートしようとはしません。
- dは実際に使用せずに終了したので
t
、戻って読み込みを終了しt
ます。問題ない。
主な違いは、ここでは名前t
とd
が互いに直接アクセスできないことです。これらはパッケージによって仲介されるcode
ため、Pythonは、実際に使用されるまで、実際に「tが何であるかを決定する」ことを完了する必要はありません。を使用from code import t
すると、値を変数に割り当てる必要があるためt
、Pythonはそれが何であるかをすぐに知る必要があります。
あなたがd.py
このように見えるようにすると、あなたは問題を見ることができます:
import code.t
print code.t
ここで、ステップ2の後、dの実行中に、実際には半分インポートされたモジュールtにアクセスしようとします。モジュールはまだ完全にインポートされていないため、パッケージにアタッチされていないため、これによりAttributeErrorが発生しますcode
。
code.t
実行が終了するまで使用が行われなかった場合は問題ないことに注意してくださいd
。これは次の場合に正常に機能しd.py
ます:
import code.t
def f():
print code.t
f
後で電話することができ、それは機能します。code.t
その理由は、実行が終了するまで使用する必要がなくd
、dが実行を終了した後、戻ってtの実行を終了できるためです。
繰り返しになりますが、ストーリーの主な教訓は、循環インポートを使用しないことです。それはあらゆる種類の頭痛につながります。代わりに、両方のモジュールによってインポートされた3番目のモジュールに共通のコードを除外します。