대규모 Python 프로젝트에서는 부적절한 아키텍처 설계로 인해 모듈 간의 상호 참조가 발생할 수 있습니다. 다음 글에서는 Python의 순환 가져오기 문제를 방지하는 방법에 대한 관련 정보를 주로 소개합니다. 도움이 필요한 친구들이 참고할 수 있습니다.
서문
Python에서 패키지를 사용할 때 순환 가져오기 문제가 발생하는 것은 매우 일반적입니다. 이 문제를 설명하기 위해 다음 패키지를 만들었습니다.
pkg ├── __init__.py ├── module_a.py └── module_b.py
그 중
__init__.py pkg를 Python 패키지로 지정
module_a.py는 module_b.py에 정의된 함수나 변수와 같은 module_b.py의 속성을 참조하는 action_a()
함수를 정의합니다. A action_b()
함수, 함수 또는 변수와 같은 module_a.py의 속성을 참조합니다 action_a()
函数,该函数引用了module_b.py中的一个attribute,如一个函数或变量
module_b.py中定义了一个action_b()
函数,该函数引用了module_a.py中的一个attribute,如一个函数或变量
这种情况下,执行该package时会抛出circular import error
错误,即循环引用,因为module_a试图去引入module_b时,而module_b首先要引入module_a,这会导致Python解释器无法执行下去。
然而,我们可以通过一些巧妙的方法,让上面的逻辑正常工作,同时避免循环引入的错误。
那么,什么时候它能正常工作,什么时候不能正常工作,而那些能够正常工作的情况又是什么原因呢?
何时它能正常工作?
1. 在module顶部引入,不要用from,相对引入,只在Python 2中有效
在module的顶部import,如import another_module
,module 中的函数以another_module.attribute
的方式引用another_module中的函数或变量等。这种方式之所以有效,是由于import another_module
是基于当前目录的相对引用,而且是一种隐式引用,如果从另一个package中引入module时,就可以失效了。另外,import another_module
这种语法在Python3 中已经不支持了,所以不要在代码中用这种方法来避免循环引入。
如:
# pkg/module_a.py from __future__ import print_function import module_b def action_a(): print(module_b.action_b.__name__) # pkg/module_b.py from __future__ import print_function import module_a def action_b(): print(module_a.action_a.__name__)
2. 在module的顶部引入,不要用from,绝对引入
在module的顶部import,使用从package开始的绝对路径,如import package.another_module
,module 中的函数以package.another_module.attribute
的方式引用another_module中的函数或变量等。之所以要挂上package name来引入,是由于import .another_module
这种形式的“相对引入”会报语法错误,而挂上package的绝对引入,Python 2和3都支持
案例:
# pkg/module_a.py from __future__ import print_function import pkg2.module_b def action_a(): print(pkg2.module_b.action_b.__name__) # pkg/module_b.py from __future__ import print_function import pkg2.module_a def action_b(): print(pkg2.module_a.action_a.__name__)
3. 在module底部引入another module的attribute,而非another module,用from
在module的底部import(至少要在被引用的attribute之后import),直接引入another module
的attribute,如from package.another_module import attribute
,相对引入也支持,如from .another_module import attribute
,module中的函数直接使用被引用的attribute即可。
如:
# pkg/module_a.py from __future__ import print_function def action_a(): print(action_b.__name__) from .module_b import action_b # pkg/module_b.py from __future__ import print_function def action_b(): print(action_a.__name__) from .module_a import action_a
4. 函数顶部引入,可以用from
在module的function顶部import,如from package import another_module
패키지 오류 실행 시 순환 가져오기가 발생합니다
오류, 즉 순환 참조입니다. module_a가 module_b를 도입하려고 시도하고 module_b가 먼저 module_a를 도입하여 Python 인터프리터가 실행될 수 없게 되기 때문입니다. 그러나 몇 가지 영리한 방법을 사용하면 루프로 인한 오류를 피하면서 위의 논리가 제대로 작동하도록 만들 수 있습니다.
그럼 언제 제대로 작동하고, 언제 제대로 작동하지 않고, 제대로 작동하는 경우의 이유는 무엇인가요?
언제부터 제대로 작동되나요?
1. 모듈 상단에서 가져오기, from을 사용하지 않음, 상대 가져오기, Python 2
import another_module</code)에서 모듈 상단에서 가져오기만 가능 >, 모듈의 함수 <code>another_module.attribute
형식의 another_module에 있는 함수 또는 변수를 참조하세요. 이 방법이 효과적인 이유는 import another_module
이 현재 디렉터리를 기준으로 한 상대 참조이며, 다른 패키지에서 모듈을 가져오면 유효하지 않게 되기 때문입니다. 또한 import another_module
구문은 Python 3에서 더 이상 지원되지 않으므로 루프 도입을 방지하려면 코드에서 이 메서드를 사용하지 마세요. # pkg/module_a.py from __future__ import print_function def action_a(): from . import module_b print(module_b.action_b.__name__) # pkg/module_b.py from __future__ import print_function def action_b(): from . import module_a print(module_a.action_a.__name__)
import package .another_module
과 같이 module의 함수는 package.another_module.attribute
형식의 another_module에 있는 함수나 변수를 참조합니다. 가져올 패키지 이름을 걸어 놓아야 하는 이유는 import .another_module
형식의 "상대 가져오기"는 구문 오류를 보고하는 반면, 패키지의 절대 가져오기는 지원되기 때문입니다. Python 2 및 3 모두🎜 🎜🎜사례: 🎜🎜🎜🎜# pkg/module_a.py from __future__ import print_function def action_a(): from .module_b import action_b print(action_b.__name__) # pkg/module_b.py from __future__ import print_function def action_b(): from .module_a import action_a print(action_a.__name__)
package.another_module 가져오기 속성
에서와 같이 다른 모듈
의 속성을 직접 도입하는 것도 지원됩니다. code>from .another_module 가져오기 속성, 모듈 내 함수는 참조된 속성을 직접 사용할 수 있습니다. 🎜🎜🎜예: 🎜🎜🎜🎜rrreee🎜🎜4 함수 상단에서 가져오려면 from🎜🎜🎜🎜을 사용하여 from과 같이 모듈의 함수 상단에서 가져올 수 있습니다. package import another_module
, 상대 가져오기도 지원합니다. 모듈이나 속성을 도입할 수 있습니다. 🎜🎜🎜 예: 🎜🎜🎜🎜rrreee🎜 또는 🎜🎜🎜🎜rrreee🎜 이 방법은 Python 2 및 3에서 지원되지만 코딩이 충분히 우아하지 않으며 코드의 가독성에 영향을 미치므로 사용하지 않는 것이 좋습니다. 🎜🎜🎜🎜🎜Note🎜 🎜🎜🎜🎜이 글에서 논의한 문제는 Python에서 패키지를 호출할 때 루프 도입을 피하는 방법입니다.🎜🎜🎜Python 모듈이 명령줄에서 직접 실행될 때 적용 가능한 상황은 정확히는 아닙니다. 똑같아🎜위 내용은 Python에서 순환 가져오기 방법을 피하는 방법에 대한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!