이미 플랫 패키지를 사용하고 있었기 때문에 중첩 된 패키지에서 발생한 문제를 예상하지 못했습니다. 여기 …
디렉토리 레이아웃
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
init .py의 내용
모두 package/__init__.py와 package/subpackage/__init__.py비어 있습니다.
의 내용 module.py
# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
내용 test.py(3 개 버전)
버전 1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
그것은 사물을 가져 오는 (일괄 가져 오기)의 나쁘고 안전하지 않은 방법이지만 작동합니다.
버전 2
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
더 안전한 방법으로 항목별로 가져 오지만 실패합니다. Python은 이것을 원하지 않습니다. “No module named module”메시지와 함께 실패합니다. 그러나…
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
… 말한다 <module 'package.subpackage.module' from '...'>. 그래서 그것은 모듈이지만 그것은 모듈이 아닙니다 / -P 😯 … 어
버전 3
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
이것은 작동합니다. 그래서 당신은 항상 overkill 접두사를 사용하거나 버전 # 1에서와 같이 안전하지 않은 방법을 사용하고 Python에서 안전하고 편리한 방법을 사용하는 것을 허용하지 않습니까? 안전하고 불필요한 긴 접두사를 피하는 더 좋은 방법은 Python이 거부하는 유일한 방법입니까? 그것을 사랑하기 때문이다 import *하거나 (이 연습을 시행하는 데 도움이되지 않습니다) 너무 긴 접두사를 사랑하기 때문에?
어려운 말로 미안하지만이 멍청한 행동을 해결하려고 노력하는 이틀입니다. 내가 어딘가에서 완전히 틀린 것이 아니라면, 파이썬의 패키지 및 하위 패키지 모델에서 무언가가 정말로 망가 졌다는 느낌이들 것입니다.
메모
- 나는
sys.path글로벌 부작용을 피하기 위해, 또는 동일한 글로벌 효과*.pth를 가지고 놀 수있는 또 다른 방법 인 파일 에 의존하고 싶지 않습니다sys.path. 솔루션이 깨끗하려면 로컬에만 있어야합니다. Python은 하위 패키지를 처리 할 수 있지만 그렇지 않은 경우에도 로컬 작업을 처리 할 수 있도록 전역 구성을 사용할 필요가 없습니다. - 나는 또한에서 가져 오기를 사용해 보았지만
package/subpackage/__init__.py아무것도 해결하지subpackage못했고 똑같이 수행 하며 알려진 모듈이 아니라고 불평print subpackage하고 모듈이라고 말합니다 (이상한 동작).
내가 완전히 틀렸을 수도 있지만 (내가 선호하는 옵션) 파이썬에 대해 많이 실망하게 만듭니다.
내가 시도한 세 가지 외에 다른 알려진 방법이 있습니까? 내가 모르는 것?
(한숨)
—– % <—– 편집 —–> % —–
지금까지의 결론 (사람들의 의견 후)
모든 패키지 참조가 전역 사전으로 이동하기 때문에 Python의 실제 하위 패키지와 같은 것은 없습니다. 즉, 로컬 패키지 참조를 관리 할 방법이 없음을 의미하는 로컬 사전이 없음을 의미합니다.
전체 접두사 또는 짧은 접두사 또는 별칭을 사용해야합니다. 에서와 같이 :
전체 접두사 버전
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
짧은 접두사 버전 (하지만 반복되는 접두사)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
또는 위의 변형입니다.
from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context
분해 된 버전
한 번에 여러 항목을 일괄 적으로 가져 오는 것이 마음에 들지 않으면 다음을 수행 할 수 있습니다.
from package.subpackage.module import attribute1, attribute2
# and etc.
내가 가장 좋아하는 취향은 아니지만 (수입 법인 당 하나의 수입 명세서를 선호 함) 개인적으로 선호하는 것이 될 수 있습니다.
업데이트 (2012-09-14) :
마침내 레이아웃에 대한 주석을 제외하고는 실제로 괜찮은 것처럼 보입니다. 위의 대신 다음을 사용했습니다.
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.
답변
import모듈을 검색 하는 방법을 오해하는 것 같습니다 . import 문을 사용하면 항상 실제 모듈 경로 (및 / 또는 sys.modules)를 검색합니다 . 이전 가져 오기로 인해 존재하는 로컬 네임 스페이스 의 모듈 객체 를 사용하지 않습니다 . 당신이 할 때 :
import package.subpackage.module
from package.subpackage import module
from module import attribute1
두 번째 줄은라는 패키지를 찾고 해당 패키지에서 package.subpackage가져옵니다 module. 이 줄은 세 번째 줄에 영향을주지 않습니다. 세 번째 줄은 호출 된 모듈을 module찾지 만 찾지 못합니다. module위의 줄에서 가져온 호출 된 개체를 “재사용”하지 않습니다 .
즉, from someModule import ...“이전에 가져온 someModule이라는 모듈에서 …”라는 의미가 아니라 “sys.path에서 찾은 someModule이라는 모듈에서 …”를 의미합니다. 모듈로 연결되는 패키지를 가져 와서 모듈의 경로를 “점진적으로”빌드하는 방법은 없습니다. 가져올 때 항상 전체 모듈 이름을 참조해야합니다.
달성하려는 목표가 명확하지 않습니다. 특정 개체 attribute1 만 가져 오려면 수행 from package.subpackage.module import attribute1하고 수행하면됩니다. package.subpackage.module원하는 이름을 가져온 후에는 오랫동안 걱정할 필요가 없습니다 .
당신이 경우 않는 다른 이름 나중에 액세스 모듈에 액세스 할 수 있도록하려면, 당신은 할 수 from package.subpackage import module당신이 다음 할 수있는 보았 듯이, 그리고 module.attribute1당신 같은 등등 많은.
당신이 원하는 경우 모두를 원하는 경우 — 즉, attribute1직접 액세스 하고 당신이 원하는 module접근, 바로 위의 두 가지를 모두 수행 :
from package.subpackage import module
from package.subpackage.module import attribute1
attribute1 # works
module.someOtherAttribute # also works
package.subpackage두 번 입력하는 것을 좋아하지 않는 경우 attribute1에 대한 로컬 참조를 수동으로 만들 수 있습니다.
from package.subpackage import module
attribute1 = module.attribute1
attribute1 # works
module.someOtherAttribute #also works
답변
# 2가 실패하는 이유 sys.modules['module']는 존재하지 않고 (가져 오기 루틴에 자체 범위가 있고 module로컬 이름을 볼 수 없음 ) module디스크에 모듈이나 패키지 가 없기 때문 입니다. 가져온 여러 이름을 쉼표로 구분할 수 있습니다.
from package.subpackage.module import attribute1, attribute2, attribute3
또한:
from package.subpackage import module
print module.attribute1
답변
전역 네임 스페이스에서 attribute1을 가져 오는 것뿐이라면 버전 3은 괜찮아 보입니다. 왜 과도한 접두사입니까?
버전 2에서는
from module import attribute1
넌 할 수있어
attribute1 = module.attribute1
