Python의 순환 가져 오기 종속성
다음 디렉터리 구조가 있다고 가정 해 보겠습니다.
a\
__init__.py
b\
__init__.py
c\
__init__.py
c_file.py
d\
__init__.py
d_file.py
에서 a
패키지의 __init__.py
의 c
패키지를 가져옵니다. 하지만 c_file.py
수입 a.b.d
.
이 프로그램은 말을, 실패 b
할 때 존재하지 않는 c_file.py
시도 가져올 a.b.d
. (그리고 우리가 가져 오는 중이었기 때문에 실제로 존재하지 않습니다.)
이 문제를 어떻게 해결할 수 있습니까?
a가 c에 의존하고 c가 a에 의존한다면, 그들은 실제로 동일한 단위입니까?
a와 c를 두 개의 패키지로 분리 한 이유를 실제로 조사해야합니다. 일부 코드를 다른 패키지로 분리해야하기 때문입니다 (둘 다 새 패키지에 종속되지만 서로가 아닌). 하나의 패키지로.
다음과 같이 가져 오기를 연기 할 수 있습니다 a/__init__.py
.
def my_function():
from a.b.c import Blah
return Blah()
즉, 실제로 필요할 때까지 가져 오기를 연기합니다. 그러나 지적 된 것과 같은 순환 종속성이 설계 문제를 나타낼 수 있으므로 패키지 정의 / 용도를 자세히 살펴볼 것입니다.
나는 이것을 몇 번 궁금해했다 (보통 서로에 대해 알아야하는 모델을 다룰 때). 간단한 해결책은 전체 모듈을 가져온 다음 필요한 것을 참조하는 것입니다.
그래서하는 대신
from models import Student
하나에
from models import Classroom
다른 하나는 그냥
import models
그런 다음 필요할 때 models.Classroom을 호출하십시오.
문제는 디렉토리에서 실행할 때 기본적으로 하위 디렉토리 인 패키지 만 후보 가져 오기로 표시되므로 abd를 가져올 수 없다는 것입니다. 그러나 b는 a의 하위 패키지이므로 bd를 가져올 수 있습니다.
정말로 abd를 가져오고 싶다면 c/__init__.py
시스템 경로를 a 위의 디렉토리로 변경하고 가져 오기를 a/__init__.py
import abc 로 변경하여이를 수행 할 수 있습니다.
귀하는 a/__init__.py
다음과 같아야합니다 :
import sys
import os
# set sytem path to be directory above so that a can be a
# package namespace
DIRECTORY_SCRIPT = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0,DIRECTORY_SCRIPT+"/..")
import a.b.c
c에서 모듈을 스크립트로 실행하려는 경우 추가 어려움이 발생합니다. 여기서 패키지 a와 b는 존재하지 않습니다. __int__.py
c 디렉토리를 해킹하여 sys.path가 최상위 디렉토리를 가리 키도록 한 다음 __init__
c 내부의 모든 모듈을 가져 와서 전체 경로를 사용하여 abd를 가져올 __init__.py
수 있습니다. 내 사용 사례에서 작동했습니다.
다음과 같은 패턴을 제안합니다. 이를 사용하면 자동 완성 및 유형 힌트가 제대로 작동 할 수 있습니다.
cyclic_import_a.py
import playground.cyclic_import_b
class A(object):
def __init__(self):
pass
def print_a(self):
print('a')
if __name__ == '__main__':
a = A()
a.print_a()
b = playground.cyclic_import_b.B(a)
b.print_b()
cyclic_import_b.py
import playground.cyclic_import_a
class B(object):
def __init__(self, a):
self.a: playground.cyclic_import_a.A = a
def print_b(self):
print('b1-----------------')
self.a.print_a()
print('b2-----------------')
이 구문을 사용하여 클래스 A 및 B를 가져올 수 없습니다.
from playgroud.cyclic_import_a import A
from playground.cyclic_import_b import B
You cannot declare the type of parameter a in class B __ init __ method, but you can "cast" it this way:
def __init__(self, a):
self.a: playground.cyclic_import_a.A = a
Another solution is to use a proxy for the d_file.
For example, let's say that you want to share the blah class with the c_file. The d_file thus contains:
class blah:
def __init__(self):
print("blah")
Here is what you enter in c_file.py:
# do not import the d_file !
# instead, use a place holder for the proxy of d_file
# it will be set by a's __init__.py after imports are done
d_file = None
def c_blah(): # a function that calls d_file's blah
d_file.blah()
And in a's init.py:
from b.c import c_file
from b.d import d_file
class Proxy(object): # module proxy
pass
d_file_proxy = Proxy()
# now you need to explicitly list the class(es) exposed by d_file
d_file_proxy.blah = d_file.blah
# finally, share the proxy with c_file
c_file.d_file = d_file_proxy
# c_file is now able to call d_file.blah
c_file.c_blah()
참고URL : https://stackoverflow.com/questions/1556387/circular-import-dependency-in-python
'Programing' 카테고리의 다른 글
Ruby on Rails 확장 성 / 성능? (0) | 2020.10.28 |
---|---|
포착되지 않은 TypeError : Object.values는 함수 JavaScript가 아닙니다. (0) | 2020.10.28 |
문자열이 C에서 다른 문자열로 시작하는지 확인하는 방법은 무엇입니까? (0) | 2020.10.28 |
슬롯에 인수 전달 (0) | 2020.10.28 |
MongoDB의 $ in 절이 순서를 보장합니까? (0) | 2020.10.27 |