Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

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

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 패키지 안의 실행 가능한 모듈에서 명시적 상대 임포트를 사용할 수 있게 하는 메커니즘을 제안하며, 이 메커니즘은 하위 호환성을 유지합니다. 현재 이러한 임포트는 PEP 328과 PEP 338 사이의 어색한 상호 작용 때문에 실패합니다.

이 PEP는 새로운 모듈 수준 속성을 추가하여, 모듈이 -m 스위치로 실행되는 경우 상대 임포트가 자동으로 동작하도록 합니다. 파일이 이름으로 실행되는 경우에는 모듈 자체에 약간의 상용구 코드를 추가하면 상대 임포트가 동작합니다.

Guido는 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 제안의 장점은 일반 코드에 미치는 영향이 모듈을 임포트할 때 추가 속성을 설정하는 데 드는 약간의 시간뿐이라는 점입니다. 패키지 이름이 모듈 전역 변수에 캐시되어 상대 임포트를 할 때마다 다시 계산할 필요가 없으므로, 상대 임포트 자체는 아주 약간 빨라질 것입니다.

참고 문헌