[python] Python : 하위 패키지 또는 하위 모듈 가져 오기

이미 플랫 패키지를 사용하고 있었기 때문에 중첩 된 패키지에서 발생한 문제를 예상하지 못했습니다. 여기 …

디렉토리 레이아웃

dir
 |
 +-- test.py
 |
 +-- package
      |
      +-- __init__.py
      |
      +-- subpackage
           |
           +-- __init__.py
           |
           +-- module.py

init .py의 내용

모두 package/__init__.pypackage/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


답변