파이썬 순환 가져 오기?
그래서이 오류가 발생합니다
Traceback (most recent call last):
File "/Users/alex/dev/runswift/utils/sim2014/simulator.py", line 3, in <module>
from world import World
File "/Users/alex/dev/runswift/utils/sim2014/world.py", line 2, in <module>
from entities.field import Field
File "/Users/alex/dev/runswift/utils/sim2014/entities/field.py", line 2, in <module>
from entities.goal import Goal
File "/Users/alex/dev/runswift/utils/sim2014/entities/goal.py", line 2, in <module>
from entities.post import Post
File "/Users/alex/dev/runswift/utils/sim2014/entities/post.py", line 4, in <module>
from physics import PostBody
File "/Users/alex/dev/runswift/utils/sim2014/physics.py", line 21, in <module>
from entities.post import Post
ImportError: cannot import name Post
동일한 import 문을 더 많이 사용하고 작동한다는 것을 알 수 있습니까? 순환 가져 오기에 대해 작성되지 않은 규칙이 있습니까? 동일한 클래스를 호출 스택 아래에서 어떻게 사용합니까?
나는 jpmc26의 대답이 결코 잘못된 것은 아니지만 순환 수입에 너무 많이 내려 간다고 생각합니다 . 올바르게 설정하면 제대로 작동 할 수 있습니다.
이를 수행하는 가장 쉬운 방법은 import my_module
대신 구문 을 사용 하는 것 from my_module import some_object
입니다. 전자는 my_module
우리를 다시 수입 하더라도 거의 항상 작동 합니다. 후자 my_object
는에 이미 정의 된 경우에만 작동 my_module
하며 순환 가져 오기에서는 그렇지 않을 수 있습니다.
귀하의 사례에 대해 구체적으로 설명하십시오 . 직접적 으로가 아니라 entities/post.py
할 일로 변경 import physics
한 다음 참조하십시오 . 마찬가지로, 변경 해야 할 다음 사용 만이 아니라 .physics.PostBody
PostBody
physics.py
import entities.post
entities.post.Post
Post
모듈 (또는 그 구성원)을 처음으로 가져올 때 모듈 내부의 코드는 다른 코드와 마찬가지로 순차적으로 실행됩니다. 예를 들어, 함수의 본문과 다르게 취급되지 않습니다. An import
은 다른 명령 (할당, 함수 호출 def
,, class
) 과 같은 명령 입니다. 가져 오기가 스크립트 상단에서 발생한다고 가정하면 다음과 같은 상황이 발생합니다.
- 당신이 가져올 때
World
에서world
의world
스크립트가 실행됩니다. world
스크립트 수입Field
원인,entities.field
스크립트가 실행하세요.- 이 프로세스는
entities.post
가져 오기를 시도했기 때문에 스크립트에 도달 할 때까지 계속 됩니다Post
entities.post
스크립트 원인physics
은 수입하려고하기 때문에 모듈이 실행되는PostBody
- 마지막으로,
physics
가져올 시도Post
에서entities.post
entities.post
모듈이 아직 메모리에 있는지 확실 하지 않지만 실제로는 중요하지 않습니다. 모듈이 메모리에 없거나 정의 실행이 완료되지Post
않았기 때문에 모듈에 아직 멤버 가 없습니다.Post
- 어느 쪽이든
Post
가져올 것이 없기 때문에 오류가 발생합니다.
따라서 "콜 스택에서 더 많이 작동"하는 것이 아닙니다. 이것은 오류가 발생한 위치에 대한 스택 추적으로, Post
해당 클래스에서 가져 오려는 중에 오류가 발생 했음을 의미합니다 . 순환 가져 오기를 사용하면 안됩니다. 기껏해야 미미한 이점 (일반적으로 이점 없음 )이 있으며 이와 같은 문제가 발생합니다. 그것은 그것을 유지하는 모든 개발자에게 부담을 주므로 깨지지 않도록 달걀 껍질 위를 걷도록 강요합니다. 모듈 조직을 리팩터링하십시오.
순환 종속성을 이해하려면 Python이 본질적으로 스크립팅 언어라는 점을 기억해야합니다. 메서드 외부의 명령문 실행은 컴파일 타임에 발생합니다. Import 문은 메서드 호출처럼 실행되며이를 이해하려면 메서드 호출처럼 생각해야합니다.
가져 오기를 수행 할 때 가져 오는 파일이 이미 모듈 테이블에 있는지 여부에 따라 발생하는 상황이 달라집니다. 그렇다면 파이썬은 현재 기호 테이블에있는 것을 사용합니다. 그렇지 않다면 파이썬은 모듈 파일을 읽기 시작하고 거기에서 찾은 모든 것을 컴파일 / 실행 / 가져옵니다. 컴파일 타임에 참조 된 심볼은 표시되었는지 여부에 따라 컴파일러에서 표시되는지 여부에 따라 달라집니다.
두 개의 소스 파일이 있다고 가정하십시오.
X.py 파일
def X1:
return "x1"
from Y import Y2
def X2:
return "x2"
파일 Y.py
def Y1:
return "y1"
from X import X1
def Y2:
return "y2"
Now suppose you compile file X.py. The compiler begins by defining the method X1, and then hits the import statement in X.py. This causes the compiler to pause compilation of X.py and begin compiling Y.py. Shortly thereafter the compiler hits the import statement in Y.py. Since X.py is already in the module table, Python uses the existing incomplete X.py symbol table to satisfy any references requested. Any symbols appearing before the import statement in X.py are now in the symbol table, but any symbols after are not. Since X1 now appears before the import statement, it is successfully imported. Python then resumes compiling Y.py. In doing so it defines Y2 and finishes compiling Y.py. It then resumes compilation of X.py, and finds Y2 in the Y.py symbol table. Compilation eventually completes w/o error.
Something very different happens if you attempt to compile Y.py from the command line. While compiling Y.py, the compiler hits the import statement before it defines Y2. Then it starts compiling X.py. Soon it hits the import statement in X.py that requires Y2. But Y2 is undefined, so the compile fails.
Please note that if you modify X.py to import Y1, the compile will always succeed, no matter which file you compile. However if you modify file Y.py to import symbol X2, neither file will compile.
Any time when module X, or any module imported by X might import the current module, do NOT use:
from X import Y
Any time you think there may be a circular import you should also avoid compile time references to variables in other modules. Consider the innocent looking code:
import X
z = X.Y
Suppose module X imports this module before this module imports X. Further suppose Y is defined in X after the import statement. Then Y will not be defined when this module is imported, and you will get a compile error. If this module imports Y first, you can get away with it. But when one of your co-workers innocently changes the order of definitions in a third module, the code will break.
In some cases you can resolve circular dependencies by moving an import statement down below symbol definitions needed by other modules. In the examples above, definitions before the import statement never fail. Definitions after the import statement sometimes fail, depending on the order of compilation. You can even put import statements at the end of a file, so long as none of the imported symbols are needed at compile time.
Note that moving import statements down in a module obscures what you are doing. Compensate for this with a comment at the top of your module something like the following:
#import X (actual import moved down to avoid circular dependency)
In general this is a bad practice, but sometimes it is difficult to avoid.
For those of you who, like me, come to this issue from Django, you should know that the docs provide a solution: https://docs.djangoproject.com/en/1.10/ref/models/fields/#foreignkey
"...To refer to models defined in another application, you can explicitly specify a model with the full application label. For example, if the Manufacturer model above is defined in another application called production, you’d need to use:
class Car(models.Model):
manufacturer = models.ForeignKey(
'production.Manufacturer',
on_delete=models.CASCADE,
)
This sort of reference can be useful when resolving circular import dependencies between two applications...."
If you run into this issue in a fairly complex app it can be cumbersome to refactor all your imports. PyCharm offers a quickfix for this that will automatically change all usage of the imported symbols as well.
I was using the following:
from module import Foo
foo_instance = Foo()
but to get rid of circular reference
I did the following and it worked:
import module.foo
foo_instance = foo.Foo()
참고URL : https://stackoverflow.com/questions/22187279/python-circular-importing
'code' 카테고리의 다른 글
오버레이 이미지에서 마우스 상호 작용 무시 (0) | 2020.09.13 |
---|---|
문자열을 동등한 Enum 값으로 변환 (0) | 2020.09.13 |
C #에서 Guid를 사용하는 방법? (0) | 2020.09.13 |
Android에서 이미지 크기를 조정하는 방법은 무엇입니까? (0) | 2020.09.13 |
Python 확장-super () Python 3 대 Python 2 사용 (0) | 2020.09.13 |