ImportError : 이름 X를 가져올 수 없습니다


540

main, vector, entity 및 physics라는 네 가지 파일이 있습니다. 오류가있는 곳이라고 생각하기 때문에 모든 코드를 게시하지 않고 가져 오기 만합니다. (원한다면 더 게시 할 수 있습니다)

본관:

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 ++로 작업했습니다. 나는 오류가 엔티티에서 두 번, 메인에서 한 번, 나중에 물리에서 가져 오기 때문이라고 생각하지만 해결 방법을 모르겠습니다. 누구든지 도울 수 있습니까?


이들이 저장된 위치와 디렉토리의 디렉토리 구조는 무엇입니까?
Ben

1
파이썬에서 루프 가져 오기에 대한이 답변을 살펴 있습니다 stackoverflow.com/questions/7199466/...
그레고르

일반적으로, 좋은 일을하는 연습을 코딩 아니에요 from <module> import <name>, 나 from <modlue> import *. 동일한 이름의 참조를 덮어 쓰지 않도록 모듈 네임 스페이스에서 가져 오는 것이 좋습니다.
Joel Cornett

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 생성자 정의에서 물리를 참조하지 않으면 Ent 바로 아래에서 mport를 이동하십시오. 그렇다면 setPhysics와 같은 메소드를 추가하여 생성자 후에 가져 오기를 사용하십시오.
Teemu Ikonen

12
@jsells C ++로 "오랫동안"작업 했으므로 두 클래스가 서로 의존해서는 안된다는 것을 알아야한다. 이것은 C ++에서 매우 중요하며 파이썬에서 # 1이 아니더라도이 규칙을 따르는 것이 좋습니다. 서로를 아는 두 개의 수업이 없습니다. 클래스 구조를 만드는 데 도움이 필요하면 나머지 코드도 게시하십시오. 정확히 어떻게 (코드의 관점에서)이된다 EntityPhysics서로 연결? 당신이하려는 일에 대한 해결 방법이 있다고 확신합니다.

7
@ user2032433 정말 '서로 알다'는 말의 의미에 달려 있습니다. 좋은 디자인은 일반적으로 단방향 종속성 트리를 생성하는 것이 사실이며 이는 일반적으로 최선의 방법입니다. 그러나 이것에는 예외가 있습니다. C ++ 클래스는 확실히 서로 순환 적으로 참조 할 수 있습니다. (선포 선언이 없으면 이것은 항상 C ++ 솔루션을 가지고 있지는 않은 파이썬의 문제입니다.
John McFarlane

93
"두 클래스가 서로 의존해서는 안된다"는 문구는 쓰레기입니다. 양방향 (양방향) 탐색은 객체 방향에서 매우 일반적입니다. books.google.co.uk/…
Martin Spamer

5
예를 들어 상태 디자인 패턴은 일반적으로 컨텍스트 클래스와 상태 인터페이스로 구현됩니다. State 인스턴스는 Context 인스턴스를 전달하여 setState를 호출 할 수 있습니다. 이를 위해서는 State가 Context에 대해 알아야하고 그 반대도 마찬가지입니다. 이 고전적인 구조는 어떻게 "코드가 잘못 되었습니까?" 사실 그것은 정확히 파이썬에서 씨름하고있는 문제이지만 Java에서 State를 구현할 때 필요하지 않았습니다.
Auspice

141

순환 의존성을 피해야하지만 파이썬에서 가져 오기를 연기 할 수 있습니다.

예를 들면 다음과 같습니다.

import SomeModule

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

이것은 (적어도 일부 경우) 오류를 피할 것입니다.


38
순환 의존성이 가장 우회
ckb

4
pep8을 기반으로, 메소드 내부로 가져 오기를하는 것은 좋은 습관이 아닙니다
TomSawyer

@TomSawyer 왜?
Kröw

@TomSawyer 나는 이것을하지 않는 것이 좋습니다,하지만 바인드의 당신을 얻을 수있는 빠른 해결책이다
bharling

117

이것은 순환 종속성입니다. 코드를 구조적으로 수정하지 않고도 해결할 수 있습니다. 에 있기 때문에 문제가 발생합니다 vector당신이 요구하는 그 entity반대의 즉시 사용 가능하게하고, 그 반대도 될 수있다. 이 문제의 원인은 준비하기 전에 모듈의 내용에 액세스하도록 요청하기 때문입니다 from x import y. 이것은 본질적으로

import x
y = x.y
del x

파이썬은 순환 의존성을 감지하고 무한한 수입 루프를 방지 할 수 있습니다. 본질적으로 일어나는 일은 모듈에 대해 빈 자리 표시자가 만들어지는 것입니다 (즉, 내용이 없음). 순환 종속 모듈이 컴파일되면 가져온 모듈을 업데이트합니다. 이것은 이런 식으로 작동합니다.

a = module() # import a

# rest of module

a.update_contents(real_a)

파이썬이 순환 종속성으로 작업 할 수 있으려면 import x스타일 만 사용해야 합니다.

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

더 이상 최상위 레벨에서 모듈의 내용을 참조하지 않기 때문에 Python은 실제로 순환 종속성의 내용에 액세스하지 않고도 모듈을 컴파일 할 수 있습니다. 최상위 레벨은 함수의 내용 (예 :)과 반대로 컴파일 중에 실행될 라인을 의미합니다 y = x.y. 모듈 내용에 액세스하는 정적 또는 클래스 변수도 문제를 일으킬 수 있습니다.


24

논리를 명확하게하는 것이 매우 중요합니다. 참조가 데드 루프가되기 때문에이 문제가 나타납니다.

논리를 변경하지 않으려면 ImportError를 일으킨 import 문을 파일의 다른 위치 (예 : 끝)에 넣을 수 있습니다.

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_module유닉스 줄 끝이 있었다. 그것들을 동일하게 변경하면 문제가 해결되었습니다. 또한 동일한 문자 인코딩이 필요합니다.


7

이미 언급했듯이 이것은 순환 종속성 에 의해 발생합니다 . 언급되지 않은 것은 파이썬 타이핑 모듈을 사용하고 타입 에 주석을 달기 위해 클래스 만 가져올 때 Forward 참조를 사용할 수 있다는 것입니다 .

형식 힌트에 아직 정의되지 않은 이름이 포함 된 경우 해당 정의는 문자열 리터럴로 표현되어 나중에 확인할 수 있습니다.

의존성을 제거하십시오 ( 가져 오기 )

from my_module import Tree

def func(arg: Tree):
    # code

하다:

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

(제거 된 import진술에 유의 )


6

가져온 다른 모듈의 이름으로 현재 파이썬 스크립트의 이름을 지정하지 마십시오

해결책 : 작동하는 Python 스크립트 이름 바꾸기

예:

  1. 당신은 일하고 있습니다 medicaltorch.py
  2. 이 스크립트에서, 당신은 : from medicaltorch import datasets as mt_datasets어디 medicaltorch설치된 모듈이 있어야하는데

이 실패합니다 ImportError. 1에서 작동하는 Python 스크립트의 이름을 바꾸십시오.


고마워, 이것은 내가 가진 문제를 해결합니다. 나는 colorama 라이브러리를 사용하고 파일 이름을 colorama.py로 지정했기 때문에 파이썬은 무엇을 가져올 지 몰랐습니다. 파일 이름을 변경하면 도움이됩니다.
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.pyfile2.py, 당신은이를 사용해야합니다 file1.py:

if __name__ == 'file1':
    # etc

의심의 경우에, 확인 assert여부를 결정하기 위해 문을__name__=='__main__'


4

가져 오기 오류를 추적하는 한 가지 방법은 각 가져 오기 파일에서 파이썬을 실행하여 불량 파일을 추적하는 것입니다.

  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!

약간의 변경으로 우리는 이것을 해결할 수 있습니다.

# 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.