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


164

내가 한 대답 내가 읽고 내가 기초 이해 생각 파이썬에서 절대 수입에 관한 질문 파이썬 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__진술이 왜 말을하지 않는 것 같으며,이 두 문서 섹션 사이에, 그리고 설명 된 행동과 실제 행동 사이에이 모순의 해결책은 무엇입니까?


답변:


104

변경 기록은 구식입니다. 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상위 디렉토리가 경로에 없으면 경로에서도 해당 디렉토리를 고정해야합니다.


2
알았어. 알았어. 그것이 바로 내 게시물이 문서화하는 동작입니다. 그럼에도 불구하고 두 가지 질문이 있습니다. (1.) "정확히 사실이 아닙니다"라면 문서가 왜 그렇게 말합니까? 와, (2), 다음, 당신을 어떻게 import string실수로 적어도 통해 강선하지 않고, 그것을 그림자 경우 sys.modules. 이것이 from __future__ import absolute_import방지하려는 의도가 아닙니까? 무엇을합니까? (PS, 저는 downvoter가 아닙니다.)
2 비트 연금술사

14
Aye, 그것은 나였습니다 ( '유용하지 않음'에 대한 공감대는 '잘못되지 않았습니다'). 하단에서 OP가 sys.path작동 방식을 이해 하고 있으며 실제 질문은 전혀 해결되지 않았다는 것이 분명합니다. 즉, 실제로 무엇을 from __future__ import absolute_import합니까?
wim

5
@ Two-BitAlchemist : 1) 변경 로그가 느슨하고 비 규범 적입니다. 2) 그림자를 그만두십시오. 심지어 통해 강선은 sys.modules당신에게 표준 라이브러리받지 않습니다 string자신의 최상위 모듈을 그림자 경우 모듈을. from __future__ import absolute_import최상위 모듈이 최상위 모듈을 가리는 것을 막기위한 것이 아닙니다. 패키지 내부 모듈이 최상위 모듈을 가리지 않도록해야합니다. pkg패키지의 일부로 파일을 실행하면 패키지의 내부 파일이 최상위로 표시되지 않습니다.
user2357112는

@ Two-BitAlchemist : 답변이 수정되었습니다. 이 버전이 더 도움이 되나요?
user2357112는

1
@storen : pkg가져 오기 검색 경로의 패키지 라고 가정 합니다 python -m pkg.main. -m파일 경로가 아닌 모듈 이름이 필요합니다.
user2357112는

44

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

$ 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 목록 하고 하위 모듈의 의미를 올바르게 처리하는 .

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


기본적으로 "현재 디렉토리"문제를 피한 좁은 경우에만 작동합니까? PEP 328 및 2.5 변경 로그에 설명 된 것보다 훨씬 약한 구현 인 것 같습니다. 문서가 정확하지 않다고 생각하십니까?
2 비트 연금술사

@ 두 BitAlchemist 사실은 무엇을 당신이 하고있는 것은 "좁은 경우"입니다. 하나의 Python 파일 만 실행하면 실행되지만 수백 개의 가져 오기가 트리거 될 수 있습니다. 패키지의 서브 모듈은 단순히 실행되어서는 안됩니다. 그게 전부입니다.
Bakuriu

python2 pkg/main2.pypython2를 시작한 다음 pkg.main2를 가져 오는 것과 다른 동작을하는 이유 는 무엇입니까?
스토 렌

1
@storen 이는 상대적 가져 오기의 동작이 변경되기 때문입니다. pkg/main2.pypython (버전 2) 을 시작 하면 패키지로 취급 되지 않습니다pkg . 사용하는 동안 python2 -m pkg.main2또는 가져 오기는 고려 pkg패키지입니다.
Bakuriu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.