PEP 366 – 메인 모듈의 명시적 상대 임포트
- Author:
- Alyssa Coghlan <ncoghlan at gmail.com>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 01-May-2007
- Python-Version:
- 2.6, 3.0
- Post-History:
- 01-May-2007, 04-Jul-2007, 07-Jul-2007, 23-Nov-2007
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 패키지 내 실행 가능 모듈에서 명시적 상대 임포트를 사용할 수 있도록 허용하는, 하위 호환되는 메커니즘을 제안합니다. 이러한 임포트는 현재 PEP 328과 PEP 338사이의 어색한 상호작용으로 인해 실패합니다.
새로운 모듈 수준 속성을 추가함으로써, 이 PEP는 모듈이 -m 스위치를 사용하여 실행되는 경우 상대 임포트가 자동으로 작동하도록 허용합니다. 모듈 자체에 소량의 보일러플레이트를 추가하면 파일이 이름으로 실행될 때 상대 임포트가 작동하도록 할 수 있습니다.
귀도는 2007년 11월에 이 PEP를 승인했습니다 [5].
제안된 변경
주요 제안 변경 사항은 새로운 모듈 수준 속성인 __package__의 도입입니다. 이 속성이 존재하면, 상대 임포트는 모듈의 __name__ 속성이 아니라 이 속성을 기반으로 이루어집니다.
현재의 __name__ 속성과 마찬가지로, __package__를 설정하는 것은 모듈을 임포트하는 데 사용되는 PEP 302 로더의 책임입니다. imp.new_module()을 사용하여 모듈 객체를 생성하는 로더는 새 속성이 자동으로 None으로 설정됩니다. 임포트 시스템이 __package__가 설정되지 않은(또는 None으로 설정된) 모듈에서 명시적 상대 임포트를 발견하면, 올바른 값(일반 모듈의 경우 __name__.rpartition('.')[0], 패키지 초기화 모듈의 경우 __name__)을 계산하여 저장합니다. __package__가 이미 설정되어 있다면 임포트 시스템은 __name__과 __path__ 속성으로부터 패키지 이름을 다시 계산하는 대신 이를 우선적으로 사용합니다.
runpy 모듈은 모듈의 __name__ 속성을 설정하는 데 사용된 이름이 아니라, 실행할 모듈을 찾는 데 사용된 이름을 기반으로 새 속성을 명시적으로 설정합니다. 이를 통해 -m 스위치로 실행된 메인 모듈에서 상대 임포트가 올바르게 작동할 수 있습니다.
메인 모듈이 파일명으로 지정된 경우, __package__ 속성은 None으로 설정됩니다. 모듈이 직접 실행될 때 상대 임포트를 허용하려면, 첫 번째 상대 임포트 문 앞에 다음과 유사한 보일러플레이트가 필요합니다:
if __name__ == "__main__" and __package__ is None:
__package__ = "expected.package.name"
이 보일러플레이트는 최상위 패키지가 이미 sys.path를 통해 접근 가능한 경우에만 충분하다는 점에 유의하십시오. 최상위 패키지가 아직 임포트 가능하지 않은 상태에서 직접 실행이 작동하도록 하려면, sys.path를 조작하는 추가 코드가 필요합니다.
이 접근 방식은 형제 모듈의 절대 임포트를 사용하는 것과 동일한 단점을 가지고 있습니다 - 스크립트가 다른 패키지나 하위 패키지로 이동하면, 보일러플레이트를 수동으로 갱신해야 합니다. 상대 임포트의 개수와 관계없이 파일당 한 번만 이 변경을 수행하면 된다는 장점이 있습니다.
__package__를 명시적으로 빈 문자열로 설정하는 것도 허용되며, 이 경우 해당 모듈로부터의 모든 상대 임포트를 비활성화하는 효과가 있다는 점에 유의하십시오(이 경우 임포트 기계는 해당 모듈을 최상위 모듈로 간주하기 때문입니다). 이는 runpy와 같은 도구가 __package__를 설정할 때 최상위 모듈에 대한 특수 사례 처리를 제공할 필요가 없음을 의미합니다.
변경 근거
메인 모듈에서 명시적 상대 임포트를 사용할 수 없는 현재의 문제는 적어도 하나의 열려 있는 SF 버그 리포트(#1510172) [1]의 주제이며, comp.lang.python에서의 적어도 몇몇 질의(가령 [2]의 Alan Isaac의 질문)에 있어서도 하나의 요인이었을 가능성이 큽니다.
이 PEP는 인터프리터 시작이나 일반적인 모듈 임포트 과정에서 어떠한 유의미한 비용도 발생시키지 않으면서, 메인 모듈에서 명시적 상대 임포트를 허용하는 해법을 제공하고자 합니다.
상대 임포트와 메인 모듈을 다루는 PEP 338의 절에서는 이 문제에 대한 추가 세부 정보와 배경을 제공합니다.
참조 구현
SVN의 리비전 47142는 메인 모듈의 실제 모듈 이름을 __module_name__ 속성에 저장하는 이 제안의 초기 변형을 구현했습니다. 그 당시 2.5가 이미 베타 단계에 있었다는 사실로 인해 이는 되돌려졌습니다.
패치 1487 [4]이 이 PEP의 제안된 구현입니다.
대안 제안
PEP 3122는 메인 모듈을 식별하는 방식을 변경하여 이 문제를 해결하자고 제안했습니다. 이는 전체적인 관점에서 보면 상당히 사소한 버그를 고치기 위해 감수하기에는 큰 하위 호환성 비용이며, 해당 PEP는 거부되었습니다 [3].
이 PEP에서 제안하는 방식의 장점은 일반적인 코드에 미치는 영향이 모듈을 임포트할 때 추가 속성을 설정하는 데 필요한 약간의 시간뿐이라는 점입니다. 패키지 이름이 모듈 전역 변수에 캐시되어 매번 상대 임포트마다 다시 계산할 필요가 없으므로, 상대 임포트 자체도 미세하게 빨라질 것입니다.
참고 자료
Copyright
This document has been placed in the public domain.