[python] __future__ import absolute_import의 실제 기능은 무엇입니까?

내가 한 대답 내가 읽고 내가 기초 이해 생각 파이썬에서 절대 수입에 관한 질문 파이썬 2.5 변경 로그를 하고 동반 PEP를 . 그러나 Python 2.5를 설치하고을 올바르게 사용하는 예제를 만들려고 할 때 from __future__ import absolute_import상황이 명확하지 않다는 것을 알고 있습니다.

위의 변경 로그에서 바로이 진술은 절대 수입 변경에 대한 나의 이해를 정확하게 요약했습니다.

다음과 같은 패키지 디렉토리가 있다고 가정 해 봅시다.

pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py

이것은 패키지라는 이름을 정의합니다 pkgpkg.main and 및 pkg.stringsubmodules를 포함 .

main.py 모듈의 코드를 고려하십시오. 명령문을 실행하면 어떻게됩니까 import string? Python 2.4 및 이전 버전에서는 먼저 패키지 디렉토리에서 상대 가져 오기를 수행하고 pkg / string.py를 찾은 다음 해당 파일의 내용을 pkg.string모듈 로 가져오고 해당 모듈은 모듈의 네임 스페이스 "string"에서 이름 에 바인딩됩니다 pkg.main.

그래서 나는이 정확한 디렉토리 구조를 만들었습니다 :

$ ls -R
.:
pkg/

./pkg:
__init__.py  main.py  string.py

__init__.py그리고 string.py비어 있습니다. main.py다음 코드를 포함합니다 :

import string
print string.ascii_uppercase

예상대로 Python 2.5에서 이것을 실행하면 다음과 같이 실패합니다 AttributeError.

$ python2.5 pkg/main.py
Traceback (most recent call last):
  File "pkg/main.py", line 2, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

그러나 2.5 변경 로그에서 추가로 다음을 발견했습니다 (강조 추가).

Python 2.5에서는 지시문을 import사용하여의 동작을 절대 가져 오기로 전환 할 수 있습니다 from __future__ import absolute_import. 이 절대 가져 오기 동작은 이후 버전 (아마도 Python 2.7)에서 기본값이됩니다. 절대 가져 오기가 기본값이면 import string표준 라이브러리 버전을 항상 찾습니다.

따라서 추가 미래 수입 지침과 pkg/main2.py동일 main.py하지만 을 만들었습니다 . 이제 다음과 같이 보입니다 :

from __future__ import absolute_import
import string
print string.ascii_uppercase

그러나 파이썬 2.5에서 이것을 실행하면 …로 실패합니다 AttributeError.

$ python2.5 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 3, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

이것은 절대 가져 오기를 사용하여 항상 std-lib 버전을 찾는 명령문과 완전히 모순 import string됩니다 . 또한 절대 가져 오기가 “새로운 기본값”동작으로 예정되어 있다는 경고에도 불구하고 지시문의 유무에 관계없이 Python 2.7을 사용하여 동일한 문제를 겪었습니다.__future__

$ python2.7 pkg/main.py
Traceback (most recent call last):
  File "pkg/main.py", line 2, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

$ python2.7 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 3, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

파이썬 3.5와 함께 또는없이 ( print문이 두 파일에서 변경 되었다고 가정 ) :

$ python3.5 pkg/main.py
Traceback (most recent call last):
  File "pkg/main.py", line 2, in <module>
    print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'

$ python3.5 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 3, in <module>
    print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'

나는 이것의 다른 변형을 테스트했습니다. 대신 string.py라는 디렉토리 – 나는 빈 모듈을 만든 string경우에만 빈 함유 __init__.py– 대신에서 수입을 발행 main.py, 나는이 cd‘에 D를 pkg하고 REPL에서 직접 수입을 실행합니다. 이러한 변형 (또는 이들의 조합) 중 어느 것도 위의 결과를 변경하지 않았습니다. __future__지시문과 절대 수입에 대해 읽은 내용으로 이것을 조정할 수 없습니다 .

이것은 다음과 같이 쉽게 설명 할 수 있는 것 같습니다 (Python 2 문서에서 왔지만이 문장은 Python 3의 동일한 문서에서 변경되지 않았습니다).

sys.path

(…)

프로그램 시작시 초기화 된이 목록의 첫 번째 항목은 path[0]Python 인터프리터를 호출하는 데 사용 된 스크립트가 포함 된 디렉토리입니다. 스크립트 디렉토리를 사용할 수없는 경우 (예 : 인터프리터가 대화식으로 호출되거나 표준 입력에서 스크립트를 읽는 경우) path[0]빈 문자열 은 파이썬이 현재 디렉토리에서 모듈을 먼저 검색하도록 지시합니다.

그래서 내가 무엇을 놓치고 있습니까? 그 __future__진술이 왜 말을하지 않는 것 같으며,이 두 문서 섹션 사이에, 그리고 설명 된 행동과 실제 행동 사이에이 모순의 해결책은 무엇입니까?



답변

변경 기록은 구식입니다. from __future__ import absolute_import어떤 것이 표준 라이브러리의 일부인지에 대해 신경 쓰지 않으며 import string절대 가져 오기가 항상 표준 라이브러리 모듈을 제공하지는 않습니다.

from __future__ import absolute_importimport string, Python은 항상 최상위가 string아닌 최상위 모듈을 찾습니다 current_package.string. 그러나 파이썬이 어떤 파일이 string모듈 인지 결정하는 데 사용하는 논리에는 영향을 미치지 않습니다 . 당신이 할 때

python pkg/script.py

pkg/script.py파이썬 패키지의 일부처럼 보이지 않습니다. 정상적인 절차에 따라, pkg디렉토리 경로에 추가하고, 모든되는 .py파일에서pkg 이 최상위 모듈처럼 보입니다. import string발견 pkg/string.py은 상대적으로 수입을하고 있기 때문에 아니지만, 때문에 pkg/string.py나타납니다 최상위 모듈로 string. 이것이 표준 라이브러리가 아니라는 사실string 모듈이 아니라는 나타나지 않습니다.

pkg패키지의 일부로 파일을 실행하려면 다음을 수행하십시오.

python -m pkg.script

이 경우 pkg 디렉토리가 경로에 추가되지 않습니다. 그러나 현재 디렉토리가 경로에 추가됩니다.

또한 상용구의 pkg/script.py일부로 파이썬을 처리하도록 상용구를 추가 할 수 있습니다pkg파일로 실행할 때도 패키지의 .

if __name__ == '__main__' and __package__ is None:
    __package__ = 'pkg'

그러나 이것은 영향을 미치지 않습니다 sys.path. pkg경로 에서 디렉토리 를 제거하려면 추가 처리가 필요 하며 pkg상위 디렉토리가 경로에 없으면 경로에서도 해당 디렉토리를 고정해야합니다.


답변

절대 가져 오기와 상대 가져 오기의 차이점은 패키지에서 모듈을 가져오고 해당 모듈에서 해당 패키지에서 다른 서브 모듈을 가져 오는 경우에만 적용됩니다. 차이점을보십시오 :

$ mkdir pkg
$ touch pkg/__init__.py
$ touch pkg/string.py
$ echo 'import string;print(string.ascii_uppercase)' > pkg/main1.py
$ python2
Python 2.7.9 (default, Dec 13 2014, 18:02:08) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pkg.main1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pkg/main1.py", line 1, in <module>
    import string;print(string.ascii_uppercase)
AttributeError: 'module' object has no attribute 'ascii_uppercase'
>>>
$ echo 'from __future__ import absolute_import;import string;print(string.ascii_uppercase)' > pkg/main2.py
$ python2
Python 2.7.9 (default, Dec 13 2014, 18:02:08) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pkg.main2
ABCDEFGHIJKLMNOPQRSTUVWXYZ
>>> 

특히:

$ python2 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 1, in <module>
    from __future__ import absolute_import;import string;print(string.ascii_uppercase)
AttributeError: 'module' object has no attribute 'ascii_uppercase'
$ python2
Python 2.7.9 (default, Dec 13 2014, 18:02:08) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pkg.main2
ABCDEFGHIJKLMNOPQRSTUVWXYZ
>>>
$ python2 -m pkg.main2
ABCDEFGHIJKLMNOPQRSTUVWXYZ

참고 python2 pkg/main2.py다른 문제가 다음 실행 가지고 python2오기 다음과 pkg.main2을 사용하는 것과 동일하다 (-m 스위치).

패키지의 서브 모듈을 실행하려면 항상 -m인터프리터가 체인을 연결하지 못하게하는 스위치를 사용 하십시오sys.path 목록 하고 하위 모듈의 의미를 올바르게 처리하는 .

또한 패키지 하위 모듈에 대해 명시 적 상대 가져 오기를 사용하는 것이 좋습니다. 실패한 경우 더 많은 의미와 오류 메시지를 제공하기 때문입니다.


답변