PEP 364 – Py3K 표준 라이브러리로의 전환
- Author:
- Barry Warsaw <barry at python.org>
- Status:
- Withdrawn
- Type:
- Standards Track
- Created:
- 01-Mar-2007
- Python-Version:
- 2.6
- Post-History:
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
PEP 3108은 Python 3.0 릴리스를 위한 Python 표준 라이브러리 재편성을 설명합니다. 이 PEP는 Python 2.x 표준 라이브러리에서 Python 3.0 표준 라이브러리로 전환하는 메커니즘을 설명합니다. 이 전환을 통해 Python 프로그래머는 Python 2.6부터 새로운 Python 3.0 라이브러리 이름을 사용할 수 있고 사용하도록 권장되며, 하위 호환성을 위해 기존 이름도 유지됩니다. 이렇게 하면 Python 프로그래머는 기존 Python 프로그램과의 상호 운용성을 희생하지 않고도 상위 호환 코드를 작성할 수 있습니다.
근거
PEP 3108은 Python 표준 라이브러리(stdlib) 재편성의 근거를 제시합니다. 라이브러리를 왜, 어떻게 재편성하는지에 대한 자세한 내용은 해당 PEP를 참고하십시오. PEP 3108이 일부 또는 전체로 채택된다면, Python 프로그래머가 Python 2.x에서 새로운 표준 라이브러리 모듈 이름으로의 전환을 시작할 수 있도록 하여 Python 2.6부터 상위 호환 코드를 작성할 수 있게 하는 것이 유리합니다.
PEP 3108은 일부 “쓸모없는 낡은 것들”, 즉 더 이상 유용하지 않거나 필요하지 않은 모듈을 제거할 것을 제안한다는 점에 유의하십시오. 제거될 모듈에는 해당 모듈의 사용을 중단하는 것 외에는 상위 호환성 문제가 없으므로, 지금 읽고 계신 이 PEP는 이 내용을 다루지 않습니다.
이 PEP는 오래된 표준 라이브러리 이름에서 새로운 표준 라이브러리 이름으로의 매핑을 유지하는 메커니즘만을 다룹니다. 구체적인 모듈 이름 변경 제안은 모두 PEP 3108을 참고하십시오. 특히 기존 이름에서 새 이름으로의 매핑에 대한 지침은 Modules to Rename이라는 제목의 절을 참고하십시오. 이 PEP에 나오는 몇 가지 예시는 설명을 위한 것일 뿐이며, 구체적인 이름 변경 권고로 사용해서는 안 됩니다.
지원되는 이름 변경
이 PEP가 명시적으로 지원하는 사용 사례는 최소 4가지입니다:
StringIO를stringio로 바꾸는 것과 같은 단순한 최상위 패키지 이름 변경;email.MIMEText를email.mime.text로 바꾸는 것과 같이, 패키지 이름 자체는 변경될 수도 있고 변경되지 않을 수도 있는 하위 패키지 이름 변경;cStringIO를cstringio로 바꾸는 것과 같은 확장 모듈 이름 변경;- 위의 모든 경우에 대한 서드파티의 이름 변경.
이 PEP가 지원하는 사용 사례 중 두 가지는 StringIO 같은 단순한 최상위 모듈의 이름 변경과 email.MIMEText 같은 패키지 내부 모듈의 이름 변경입니다.
전자의 경우, PEP 3108은 현재 PEP 8의 권고에 따라 StringIO의 이름을 stringio로 바꿀 것을 권장합니다.
후자의 경우, Python 2.5와 함께 배포된 email 4.0 패키지가 이미 email.MIMEText를 email.mime.text로 이름을 바꾸었습니다. 다만 email 패키지 내부에서 일회성의, 유례없이 편법적인 방식으로 처리했습니다. 이 PEP에서 설명하는 메커니즘은 모든 모듈 이름 변경을 처리할 수 있을 만큼 범용적이므로, (이전 Python 버전과의 하위 호환성을 위한 경우를 제외하면) Python 2.5의 편법이 필요 없어집니다.
추가적인 사용 사례는 C 확장 모듈의 이름 변경을 지원하는 것입니다. C 모듈의 새 이름을 임포트할 수 있기만 하면, 해당 모듈을 새 이름으로 다시 매핑할 수 있습니다. 예를 들어 cStringIO를 cstringio로 이름을 바꾸는 경우입니다.
서드파티 패키지의 이름 변경도 지원되며, 이는 모든 Python 모듈에서 접근할 수 있는 여러 공개 인터페이스를 통해 이루어집니다.
재매핑은 재귀적으로 수행되지 않습니다.
.mv 파일
재매핑 파일은 .mv 파일이라고 부르며, 이 접미사는 Unix mv(1) 명령을 연상시키도록 선택되었습니다. .mv 파일은 단순한 줄 단위 텍스트 파일입니다. 빈 줄과 #으로 시작하는 줄은 모두 무시됩니다. 그 밖의 모든 줄에는 공백으로 구분된 두 개의 필드가 있어야 합니다. 첫 번째 필드는 이전 모듈 이름이고, 두 번째 필드는 새 모듈 이름입니다. 두 모듈 이름은 모두 점으로 구분된 전체 경로 이름으로 지정해야 합니다. 다음은 Python 2.6의 .mv 파일 예시입니다:
# Map the various string i/o libraries to their new names
StringIO stringio
cStringIO cstringio
.mv 파일은 파일 시스템의 어디에나 둘 수 있으며, 이를 파싱하고 그 안의 재매핑을 등록하는 프로그래밍 인터페이스가 제공됩니다. 기본적으로 Python이 시작될 때 oldlib 패키지에 있는 모든 .mv 파일을 읽고, 그 재매핑을 자동으로 등록합니다. 최상위 Python 2.x 표준 라이브러리 모듈에 대한 모든 모듈 재매핑은 이곳에 지정해야 합니다.
구현 명세
이 절에서는 Python 2.x에서 모듈 이름 변경을 구현하는 방식에 대한 전체 명세를 제공합니다. 핵심 메커니즘은 PEP 302에 설명된 다양한 임포트 훅에 기반합니다. 구체적으로 sys.path_importer_cache, sys.path, sys.meta_path를 모두 사용하여 필요한 기능을 제공합니다.
Python의 임포트 메커니즘이 초기화되면 oldlib 패키지가 임포트됩니다. oldlib 안에는 OldStdlibLoader라는 클래스가 있습니다. 이 클래스는 PEP 302 인터페이스를 구현하며, 인자 없이 자동으로 인스턴스화됩니다. 생성자는 oldlib 패키지 디렉터리에 있는 모든 .mv 파일을 읽고, 그 .mv 파일들에 있는 모든 재매핑을 자동으로 등록합니다. 이러한 방식으로 Python 2.x 표준 라이브러리가 재매핑됩니다.
다른 Python 모듈에서 OldStdlibLoader 클래스를 인스턴스화해서는 안 됩니다. 대신 sys.stdlib_remapper 인스턴스를 통해 전역 OldStdlibLoader 인스턴스에 접근할 수 있습니다. 재매핑 메커니즘에 프로그래밍 방식으로 접근하려면 이 인스턴스를 사용하십시오.
중요한 구현 세부 사항이 하나 있습니다. PEP 302 API에서 요구하는 대로, 우리의 리매핑 로더를 훅으로 연결하기 위해 sys.path와 모듈 __path__ 속성에 매직 문자열이 추가됩니다. 이 매직 문자열은 현재 <oldlib>이며, <로 시작하는 모든 sys.path 항목을 특별하게 취급하도록 Python의 site.py 파일을 일부 변경해야 했습니다. 구체적으로 말하면, 이 항목들을 절대 파일 이름으로 바꾸려고 시도하지 않습니다(애초에 파일 이름이 아니기 때문입니다).
재매핑 임포트 훅이 동작하려면 모듈이나 패키지가 물리적으로 새 이름 아래에 있어야 합니다. 임포트 훅은 아직 임포트되지 않았고 Python의 내장 임포트 규칙으로 임포트할 수 없는 모듈만 잡아내기 때문입니다. 따라서 어떤 모듈이 예를 들어 Lib/StringIO.py에서 Lib/stringio.py로 옮겨졌고 이전 모듈의 .pyc 파일이 제거되었다면, 재매퍼가 없을 경우 다음은 실패합니다:
import StringIO
반면 재매퍼가 있으면 이 실패하는 임포트를 잡아내어 등록된 재매핑에서 이전 이름을 조회하며, 이 경우 새 이름 stringio를 찾게 됩니다. 그런 다음 재매퍼는 새 이름으로 임포트를 시도하고, 성공하면 그 결과 모듈을 이전 이름과 새 이름 모두로 sys.modules에 바인딩합니다. 따라서 위의 임포트를 실행하면 sys.modules에 ‘StringIO’와 ‘stringio’ 항목이 생기며, 두 항목은 모두 정확히 같은 모듈 객체를 가리킵니다.
모든 .mv 파일을 다른 곳으로 옮기거나 별도의 시작 코드에서 프로그램적으로 제거하는 것 외에는 재매핑 메커니즘을 비활성화하는 방법을 제안하지 않는다는 점에 유의하십시오. Python 3.0에서는 재매핑이 제거되어 “새” 이름만 남게 됩니다.
프로그래밍 인터페이스
sys.stdlib_remapper 객체에 여러 메서드가 추가되며, 서드파티 패키지는 이를 사용하여 자체 재매핑을 등록할 수 있습니다. 그러나 어떤 경우에도 옛 이름에서 새 이름으로 가는 매핑은 오직 하나뿐이라는 점에 유의하십시오. 두 .mv 파일이 같은 옛 이름에 대해 서로 다른 매핑을 담고 있거나, 이미 재매핑된 옛 이름으로 프로그램적 호출이 이루어지면 이전 매핑은 사라집니다. 이는 이미 임포트된 모듈에는 영향을 주지 않습니다.
sys.stdlib_remapper 객체에서 다음 메서드를 사용할 수 있습니다:
read_mv_file(filename)– 주어진 파일을 읽고 그 파일에서 찾은 모든 재매핑을 등록합니다.read_directory_mv_files(dirname, suffix='.mv')– 주어진 디렉터리의 목록을 조회하여, 그 디렉터리에서 접미사(기본값은.mv)가 일치하는 모든 파일을 읽습니다. 파싱한 각 파일에 대해 그 파일에서 찾은 모든 재매핑을 등록합니다.set_mapping(oldname, newname)– 옛 모듈 이름에서 새 모듈 이름으로 가는 새 매핑을 등록합니다. 둘 다 모듈의 전체 점 구분 경로 이름이어야 합니다. newname은None일 수 있으며, 이 경우 oldname에 대한 기존 매핑이 있으면 제거됩니다(기존 매핑이 없어도 오류가 아닙니다).get_mapping(oldname, default=None)– 주어진 oldname에 대해 등록된 newname을 반환합니다. 등록된 재매핑이 없으면 default를 반환합니다.
미해결 문제
- 모든 재매핑을 비활성화하는 명령줄 스위치나 환경 변수, 또는 둘 다를 두어야 합니까?
- 재매핑이 재귀적으로 일어나야 합니까?
- 패키지의 __init__.py가 로드될 때 패키지 디렉터리에서 .mv 파일을 자동으로 파싱해야 합니까? 그렇게 하면 패키지가 자체 재매핑을 위한 .mv 파일을 쉽게 포함할 수 있습니다. email 패키지의
.mv파일을 oldlib 패키지가 아니라 email 패키지 안에 둘 경우, email 패키지가 현재 해야 하는 일과 비교해 보십시오:# Expose old names import os, sys sys.stdlib_remapper.read_directory_mv_files(os.path.dirname(__file__))
저는 패키지 디렉터리에 들어 있을 수 있는
.mv파일을 자동으로 읽어야 한다고 생각합니다.
참조 구현
참조 구현은 (이 글을 쓰는 시점 기준) 현재 Python 2.6 svn 트렁크 상태에 대한 패치 형태로, SourceForge 패치 #1675334 [1]로 제공됩니다. 이 패치에는 cStringIO를 cstringio로 이름을 바꾸는 변경이 포함되어 있지만, 이는 주로 예시와 단위 테스트를 위한 것이라는 점에 유의하십시오. 이 패치가 받아들여진다면, 이 변경을 다른 PEP 3108 변경 사항으로 분리하는 것이 좋을 수 있습니다.
참고 문헌
Copyright
This document has been placed in the public domain.