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

Python 개선 제안 한국어 번역

PEP 273 – Zip 아카이브에서 모듈 임포트하기

Author:
James C. Ahlstrom <jim at interet.com>
Status:
Final
Type:
Standards Track
Created:
11-Oct-2001
Python-Version:
2.3
Post-History:
26-Oct-2001

Table of Contents

번역·라이선스 안내

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

초록

이 PEP는 zip 아카이브에서 *.py, *.py[co] 형태의 파이썬 모듈과 패키지를 임포트하는 기능을 추가합니다. os.listdir을 사용할 수 있는 경우, 동일한 코드가 일반적인 디렉터리 임포트를 빠르게 하는 데도 사용됩니다.

참고

Zip 임포트는 Python 2.3에 추가되었지만, 최종 구현은 이 PEP에서 설명하는 방식과는 다른 접근 방식을 사용합니다. 2.3 구현은 SourceForge 패치 #652586 [1]이며, PEP 302에서 설명하는 새로운 임포트 후크를 추가합니다.

따라서 이 PEP의 나머지 부분은 역사적인 관심사일 뿐입니다.

명세

현재 sys.path는 문자열로 된 디렉터리 이름들의 리스트입니다. 이 PEP가 구현되면 sys.path의 항목이 zip 파일 아카이브를 가리키는 문자열이 될 수 있습니다. Zip 아카이브는 패키지 임포트를 지원하기 위해 서브디렉터리 구조를 포함할 수 있습니다. Zip 아카이브는 서브디렉터리와 정확히 동일하게 임포트를 충족시킵니다.

이 구현은 파이썬 코어 내에 C 코드로 되어 있으며, 지원되는 모든 파이썬 플랫폼에서 동작합니다.

Zip 아카이브에는 어떤 파일이든 있을 수 있지만, *.py*.py[co] 파일만 임포트에 사용할 수 있습니다. 동적 모듈(*.pyd, *.so)의 zip 임포트는 허용되지 않습니다.

sys.path가 현재 기본 디렉터리 이름들을 가지고 있는 것처럼, 기본 zip 아카이브 이름도 추가됩니다. 그렇지 않으면 아카이브로부터 모든 파이썬 라이브러리 파일을 임포트할 방법이 없습니다.

서브디렉터리 등가성

Zip 아카이브는 현재와 미래의 규칙에 기반한 패키지 임포트를 지원할 수 있도록 서브디렉터리 트리와 정확히 동일하게 취급되어야 합니다. 모든 zip 데이터는 중앙 디렉터리(Central Directory)에서 가져오며, 그 데이터는 올바라야 하고, 엉망인 zip 파일은 지원되지 않습니다.

sys.path에 “/A/B/SubDir”와 “/C/D/E/Archive.zip”이 들어 있고, Q 패키지에서 modfoo를 임포트하려 한다고 가정해 봅시다. 그러면 import.c는 경로와 확장자의 목록을 생성하고 해당 파일을 찾습니다. 생성된 경로의 목록은 zip 임포트라고 해서 달라지지 않습니다. import.c가 “/A/B/SubDir/Q/R/modfoo.pyc” 경로를 생성한다고 가정해 봅시다. 그러면 이는 “/C/D/E/Archive.zip/Q/R/modfoo.pyc” 경로도 생성합니다. SubDir 경로를 찾는 것은 아카이브 안에서 “Q/R/modfoo.pyc”를 찾는 것과 정확히 동일합니다.

/A/B/SubDir/*와 그 모든 서브디렉터리를 zip으로 압축한다고 가정해 봅시다. 그러면 여러분의 zip 파일은 서브디렉터리가 그랬던 것과 마찬가지로 임포트를 충족시킬 것입니다.

그렇지만 완전히 그런 것은 아닙니다. zip 파일에서는 동적 모듈을 충족시킬 수 없습니다. 동적 모듈은 .dll, .pyd, .so 같은 확장자를 가집니다. 이들은 운영체제에 의존적이며, 아마 파일에서만 로드할 수 있습니다. zip 파일에서 동적 모듈을 추출하여 일반 파일로 기록한 다음 로드하는 것이 가능할 수도 있습니다. 하지만 그렇게 하려면 임시 파일을 만들고 모든 dynload_*.c를 다루어야 하는데, 이는 아마 좋은 방안이 아닙니다.

*.pyc를 임포트하려 할 때 이를 사용할 수 없으면 대신 *.pyo가 사용됩니다. *.pyo를 찾을 때도 그 반대가 성립합니다. *.pyc*.pyo 중 어느 것도 사용할 수 없거나 매직 넘버가 유효하지 않으면 *.py가 컴파일되어 임포트를 충족시키는 데 사용되지만, 컴파일된 파일은 저장되지 않습니다. 평소 파이썬은 이를 *.py와 같은 디렉터리에 기록하지만, 물론 zip 파일에 기록하고 싶지는 않습니다. zip 아카이브의 디렉터리에 기록할 수도 있겠지만, 예를 들어 그곳이 /usr/bin이라면 어수선해지므로 바람직하지 않습니다.

컴파일된 파일을 기록하지 못하면 zip 임포트가 매우 느려지는데, 사용자는 아마 무엇이 잘못되었는지 알아내지 못할 것입니다. 따라서 *.pyc*.pyo*.py와 함께 아카이브에 넣는 것이 가장 좋습니다.

효율성

zip 아카이브에서 파일을 찾는 유일한 방법은 선형 검색입니다. 그래서 sys.path의 각 zip 파일마다 이름을 한 번 검색하여, 이름과 그 밖의 관련 데이터를 정적 파이썬 딕셔너리에 넣습니다. 키는 sys.path의 아카이브 이름과 아카이브 내 파일 이름(하위 디렉터리 포함)을 결합한 것입니다. 이는 정확히 import.c가 생성하는 이름이며, 조회를 쉽게 만듭니다.

동일한 메커니즘이 디렉터리(비-zip) 임포트를 빠르게 하는 데도 사용됩니다. 아래를 참조하십시오.

zlib

압축된 zip 아카이브는 압축 해제를 위해 zlib이 필요합니다. 다른 임포트에 앞서 우리는 zlib의 임포트를 시도합니다. zlib을 사용할 수 없으면 압축된 파일의 임포트는 “missing zlib” 메시지와 함께 실패합니다.

부팅

파이썬은 site.py 자체를 임포트하며, 이는 os, nt, ntpath, stat, UserDict를 임포트합니다. 또한 더 많은 모듈을 임포트할 수 있는 sitecustomize.py도 임포트합니다. zip 임포트는 site.py가 임포트되기 전에 사용 가능해야 합니다.

sys.path에 기본 디렉터리들이 있는 것처럼, 기본 zip 아카이브도 하나 이상 있어야 합니다.

문제는 그 이름이 무엇이어야 하는가입니다. 이름은 파이썬 버전과 연결되어야 하는데, 그래야 같은 컴퓨터에 여러 파이썬 버전이 있더라도 파이썬 실행 파일이 해당 라이브러리를 올바르게 찾을 수 있습니다.

sys.path에 이름을 하나 추가합니다. Unix에서는 디렉터리가 sys.prefix + "/lib"이고, 파일 이름은 "python%s%s.zip" % (sys.version[0], sys.version[2])입니다. 따라서 Python 2.2와 접두사 /usr/local의 경우, 경로 /usr/local/lib/python2.2/는 이미 sys.path에 있으며, /usr/local/lib/python22.zip이 추가됩니다. Windows에서는 파일이 python22.dll의 전체 경로이며, “dll”이 “zip”으로 대체됩니다. zip 아카이브 이름은 항상 sys.path의 두 번째 항목으로 삽입됩니다. 첫 번째 항목은 main.py의 디렉터리입니다(Tim에게 감사합니다).

디렉터리 임포트

zip 임포트 속도를 높이는 데 사용된 정적 Python 딕셔너리는 일반 디렉터리 임포트 속도를 높이는 데에도 사용할 수 있습니다. zip 아카이브가 아닌 sys.path의 각 항목에 대해 os.listdir을 호출하고, 디렉터리 내용을 딕셔너리에 추가합니다. 그런 다음 이중 루프에서 fopen()을 호출하는 대신, 딕셔너리를 확인하기만 합니다. 이는 임포트 속도를 크게 향상시킵니다. os.listdir이 존재하지 않으면, 딕셔너리는 사용되지 않습니다.

벤치마크

사례 원본 2.2a3 os.listdir 사용 Zip 비압축 Zip 압축
1 3.2 2.5 3.2->1.02 2.3 2.5 2.3->0.87 1.66->0.93 1.5->1.07
2 2.8 3.9 3.0->1.32 사례 1과 동일합니다.
3 5.7 5.7 5.7->5.7 2.1 2.1 2.1->1.8 1.25->0.99 1.19->1.13
4 9.4 9.4 9.3->9.35 케이스 3과 동일합니다.

케이스 1: 로컬 드라이브 C:, sys.path가 기본값을 가집니다. 케이스 2: 로컬 드라이브 C:, 파일이 있는 디렉터리가 sys.path의 끝에 위치합니다. 케이스 3: 네트워크 드라이브, sys.path가 기본값을 가집니다. 케이스 4: 네트워크 드라이브, 파일이 있는 디렉터리가 sys.path의 끝에 위치합니다.

벤치마크는 Pentium 4 클론, 1.4GHz, 256Meg에서 수행되었습니다. 이 머신은 Linux/Samba 네트워크 서버와 함께 Windows 2000을 실행하고 있었습니다. 시간은 초 단위이며, 약 100개의 Lib 모듈을 임포트하는 데 걸린 시간입니다. 케이스 2와 4는 “올바른” 디렉터리가 sys.path의 끝으로 이동되어 있습니다. “Uncomp”는 압축되지 않은 zip 아카이브를 의미하고, “Compr”는 압축된 것을 의미합니다.

초기 시간은 시스템을 재부팅한 직후의 값이며, “->” 뒤의 시간은 반복 실행 후의 값입니다. 재부팅 후 C:에서 임포트하는 시간은 “Original” 케이스에서 상당히 변동이 크지만, 더 현실적입니다.

커스텀 임포트

이 로직은 필요한 파이썬 모듈(이 경우 os)을 사용할 수 있게 될 때까지 기본 검색을 사용하여 임포트하는 능력을 보여줍니다. 이는 커스텀 임포터를 부트스트랩하는 데 사용될 수 있습니다. 예를 들어, __init__.py에 “importer()”가 존재하면, 이것이 임포트에 사용될 수 있습니다. “importer()”는 os와 다른 모듈들을 자유롭게 임포트할 수 있으며, 이들은 기본 메커니즘에 의해 충족됩니다. 이 PEP는 어떠한 커스텀 임포터도 정의하지 않으며, 이 노트는 정보 제공만을 위한 것입니다.

구현

C 구현은 SourceForge 패치 492105로 제공됩니다. 패치 652586과 현재 CVS에 의해 대체되었습니다. [2]

더 새로운 버전(Paul Moore가 최근 CVS에 맞게 업데이트함)은 645650입니다. 패치 652586과 현재 CVS에 의해 대체되었습니다. [3]

Just van Rossum의 경쟁 구현은 652586이며, 이는 PEP 302의 최종 구현의 기반이 되었습니다. PEP 273PEP 302의 임포트 훅을 사용하여 구현되었습니다. [1]

참고 문헌