ImportError:名前Xをインポートできません


540

メイン、ベクター、エンティティ、物理学という4つの異なるファイルがあります。私はそれがエラーがあるところだと思うので、私はすべてのコードを投稿するのではなく、インポートだけをします。(必要に応じて、さらに投稿できます)

メイン:

import time
from entity import Ent
from vector import Vect
#the rest just creates an entity and prints the result of movement

エンティティ:

from vector import Vect
from physics import Physics
class Ent:
    #holds vector information and id
def tick(self, dt):
    #this is where physics changes the velocity and position vectors

ベクター:

from math import *
class Vect:
    #holds i, j, k, and does vector math

物理:

from entity import Ent
class Physics:
    #physics class gets an entity and does physics calculations on it.

次にmain.pyから実行すると、次のエラーが発生します。

Traceback (most recent call last):
File "main.py", line 2, in <module>
    from entity import Ent
File ".../entity.py", line 5, in <module>
    from physics import Physics
File ".../physics.py", line 2, in <module>
    from entity import Ent
ImportError: cannot import name Ent

私はPythonに非常に慣れていませんが、長い間C ++を使用してきました。エラーはエンティティを2回インポートしたことが原因であると思います。誰か助けてもらえますか?


それらが格納されているディレクトリとどのディレクトリのディレクトリ構造は何ですか?
ベン

1
Pythonでのループインポートに関するこの回答をご覧ください。stackoverflow.com
Gregor

一般にfrom <module> import <name>、やを行うのは良いコーディング方法ではありませんfrom <modlue> import *。同じ名前の参照が上書きされる可能性を防ぐために、モジュールの名前空間の下にインポートする方がよい
Joel Cornett、2012

1
@jsellsあなたは自分のクラスを呼び出す必要がありますEntityし、Vector代わりにEnt及びVect、そのような名前を短くする理由はありません。そして、はい、import vectorそれから使用しx = vector.Vector(0,0,0)ます。

7
@Kevinさん、Javaをよく知っているので、作者の最初の文が循環依存関係がJavaの「かなり一般的な慣習」であるというこの2008年の記事の印象はどうですか?
HeyWatchこの

回答:


502

循環依存インポートがあります。physics.py輸入されたentityクラスが前にEnt定義されており、physics輸入しようとentity、すでに初期化されます。モジュールphysicsからの依存関係を削除しentityます。


5
コードをリファクタリングする以外にできることは多くありません。Entコンストラクター定義でPhysicsを参照しない場合は、mportをEntのすぐ下に移動します。その場合は、setPhysicsなどのメソッドを追加して、コンストラクターの後にインポートを有効にします。
Teemu Ikonen

12
@jsells C ++を「長い間」使用してきたので、2つのクラスが相互に依存してはならないことを知っておく必要があります。これはC ++では非常に重要であり、Pythonの#1ではない場合でも、このルールに従うことは非常に良い考えです。お互いを知っている2つのクラスは決してありません。クラスの構造を作成する際にサポートが必要な場合は、残りのコードも投稿してください。どのように正確に(コードの面で)されているEntityPhysics、相互にリンクされていますか?あなたがやろうとしていることの回避策があると私は確信しています。

7
@ user2032433それは本当にあなたが「お互いを知る」という意味に依存します。優れた設計は通常、一方向の依存関係のツリーを生成することは事実であり、これが通常は最良のアプローチです。しかし、これには例外があります。C ++クラスは循環的に相互に参照できます。(それらを相互に構成することは不可能ですが)前方宣言なしでは、これは常にC ++ソリューションを備えているわけではないPythonの問題です。
ジョンマクファーレン2014年

93
「2つのクラスが相互に依存してはならない」という記述はごみです。双方向(双方向)ナビゲーションは、オブジェクト指向では非常に一般的です。 books.google.co.uk/...
マーティンスパマ

5
(たとえば)状態設計パターンは、通常、ContextクラスとStateインターフェースで実装されます。StateのインスタンスにはContextインスタンスが渡されるため、setStateを呼び出すことができます。これには、州がコンテキストについて知る必要があり、逆もまた同様です。この古典的な構成はどのようにして「コードが悪い」のですか?実際、それはまさに私がPythonで取り組んでいる問題ですが、JavaでStateを実装したときにそうである必要はありませんでした。
オースパイス2017

141

循環依存関係を確実に回避する必要がありますが、Pythonでインポートを延期することができます。

例えば:

import SomeModule

def someFunction(arg):
    from some.dependency import DependentClass

これは(少なくとも一部のインスタンスでは)エラーを回避します。


38
循環依存は回避するのが最も良い
ckb

4
pep8をベースにして、メソッド内にインポートを置くのは良い習慣ではありません
TomSawyer

@TomSawyerなんで?
Kröw

@TomSawyerこれはお勧めしませんが、それはあなたを束縛から
外す

117

これは循環依存です。コードを構造的に変更することなく解決できます。問題が発生するのは、vectorあなたがentityすぐに使用できるようにすることを要求し、その逆の場合です。この問題の理由は、モジュールの準備が整う前に、を使用して、モジュールのコンテンツへのアクセスを要求するためですfrom x import y。これは本質的に同じです

import x
y = x.y
del x

Pythonは循環依存関係を検出し、インポートの無限ループを防ぐことができます。基本的には、空のプレースホルダーがモジュール用に作成される(つまり、コンテンツがない)だけです。循環依存モジュールがコンパイルされると、インポートされたモジュールが更新されます。これはこのようなものです。

a = module() # import a

# rest of module

a.update_contents(real_a)

Pythonが循環依存関係を処理できるようにするには、import xスタイルのみを使用する必要があります。

import x
class cls:
    def __init__(self):
        self.y = x.y

最上位のモジュールのコンテンツを参照しなくなったため、Pythonは循環依存関係のコンテンツに実際にアクセスする必要なく、モジュールをコンパイルできます。トップレベルとは、関数の内容(例:)とは対照的に、コンパイル中に実行される行を意味しy = x.yます。モジュールのコンテンツにアクセスする静的変数またはクラス変数も問題を引き起こします。


24

ロジックを明確にすることは非常に重要です。参照がデッドループになるため、この問題が発生します。

ロジックを変更したくない場合は、ImportErrorの原因となったいくつかのインポートステートメントをファイルの別の位置、たとえば末尾に置くことができます。

a.py

from test.b import b2

def a1():
    print('a1')
    b2()

b.py

from test.a import a1

def b1():
    print('b1')
    a1()

def b2():
    print('b2')

if __name__ == '__main__':
    b1()

インポートエラーが発生します。 ImportError: cannot import name 'a1'

しかし、以下のようにAのtest.b import b2の位置を変更すると、

a.py

def a1():
    print('a1')
    b2()

from test.b import b2

そして、私たちは欲しいものを手に入れることができます:

b1
a1
b2

18

これは循環依存です。この問題は、必要な場所でインポートモジュール、クラス、または関数を使用して解決できます。このアプローチを使用すると、循環依存を修正できます

A.py

from B import b2
def a1():
    print('a1')
    b2()

B.py

def b1():
   from A import a1
   print('b1')
   a1()

def b2():
   print('b2')
if __name__ == '__main__':
   b1() 

17

別の理由でこのエラーも発生しました...

from my_sub_module import my_function

メインスクリプトにはWindowsの行末がありました。my_sub_moduleUNIXの行末がありました。それらを同じになるように変更すると、問題が修正されました。また、同じ文字エンコーディングが必要です。


7

すでに述べたように、これは循環依存によって引き起こされます。言及されていないのは、Python タイピングモジュールを使用していて、タイプの注釈付けにのみ使用されるクラスをインポートする場合、前方参照を使用できることです。

タイプヒントにまだ定義されていない名前が含まれている場合、その定義は文字列リテラルとして表現され、後で解決される場合があります。

依存関係(インポート)を削除します(例:

from my_module import Tree

def func(arg: Tree):
    # code

行う:

def func(arg: 'Tree'):
    # code

(削除されたimportステートメントに注意してください)


6

現在のPythonスクリプトに、インポートする他のモジュールの名前を付けないでください

解決策:作業中のPythonスクリプトの名前を変更する

例:

  1. あなたは働いています medicaltorch.py
  2. そのスクリプトでは、あなたが持っている:from medicaltorch import datasets as mt_datasetsどこmedicaltorchにインストールモジュールであると考えられます

これはで失敗しますImportError。1で作業中のPythonスクリプトの名前を変更するだけです。


おかげで、これは私が抱えていた問題を解決します。coloramaライブラリとcolorama.pyという名前のファイルを使用したので、pythonは何をインポートすべきかわかりませんでした。ファイル名を変更すると役立ちます。
Marek Bodziony

5

これはまだここには表示されません。これは信じられないほど愚かですが、正しい変数/関数をインポートしていることを確認してください。

このエラーが発生しました

ImportError:名前IMPLICIT_WAITをインポートできません

私の変数は実際にだったのでIMPLICIT_TIMEOUT

正しい名前を使用するようにインポートを変更したときに、エラーが発生しなくなりました🤦‍♂️


1
私はなぜfrom PIL import Pillowうまくいかなかったのかを理解しようとする誰かを殺す準備ができていました。😠
aalaap

5

file1.pyからインポートしfile2.pyてこれを使用した場合:

if __name__ == '__main__':
    # etc

その中に以下の変数をfile1.py インポートすることができませんfile2.pyので、__name__ 等しくありません __main__

からfile1.pyに何かをインポートfile2.pyする場合は、これをで使用する必要がありますfile1.py

if __name__ == 'file1':
    # etc

疑問がある場合はassert__name__=='__main__'


4

インポートエラーを追跡する1つの方法は、インポートされた各ファイルでpythonを実行して不良ファイルを追跡しようとすることです。

  1. あなたは次のようなものを得ます:

    python ./main.py

    ImportError:名前Aをインポートできません

  2. 次に起動します:

    python ./modules/a.py

    ImportError:名前Bをインポートできません

  3. 次に起動します:

    python ./modules/b.py

    ImportError:名前Cをインポートできません(一部の存在しないモジュールまたはその他のエラー)


3

また、OPには直接関係ありませんが、新しいオブジェクトをモジュールに追加した後にPyCharm Pythonコンソールの再起動に失敗することも、非常に混乱する良い方法です。ImportError: Cannot import name ...

紛らわしいのは、PyCharm コンソールでインポートオートコンプリートしますが、インポートが失敗することです。


2

問題は明らかです:内の名前とモジュール間の循環依存関係entityphysics

モジュール全体またはクラスのみのインポートに関係なく、名前をロードする必要があります。

この例を見てください:

# a.py
import b
def foo():
  pass
b.bar()
# b.py
import a
def bar():
  pass
a.foo()

これは次のようにコンパイルされます:

# a.py
# import b
# b.py
# import a # ignored, already importing
def bar():
  pass
a.foo()
# name a.foo is not defined!!!
# import b done!
def foo():
  pass
b.bar()
# done!

1つのわずかな変更でこれを解決できます。

# a.py
def foo():
  pass
import b
b.bar()
# b.py
def bar():
  pass
import a
a.foo()

これは次のようにコンパイルされます:

# a.py
def foo():
  pass
# import b
# b.py
def bar():
  pass
# import a # ignored, already importing
a.foo()
# import b done!
b.bar()
# done!

2

私の場合、Jupyterノートブックで作業していましたが、これは、作業ファイル内でクラス/関数を定義したときにインポートがすでにキャッシュされているために発生していました。

Jupyterカーネルを再起動すると、エラーが消えました。


1

この質問者に特に関係はありませんが、インポートのクラス名がインポート元のファイルの定義と一致しない場合、この同じエラーが表示されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.