PEP 491 – Wheel 바이너리 패키지 형식 1.9
- Author:
- Daniel Holth <dholth at gmail.com>
- Discussions-To:
- Distutils-SIG list
- Status:
- Deferred
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 16-Apr-2015
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 “wheel”이라는 Python용 빌드된 패키지 형식의 두 번째 버전을 설명합니다. Wheel은 Python 전용의 재배치 가능한 패키지 형식을 제공하며, 이 형식을 사용하면 매번 소스에서 다시 빌드하는 것보다 더 빠르고 예측 가능하게 소프트웨어를 설치할 수 있습니다.
wheel은 특별한 형식의 파일 이름과 .whl 확장자를 가진 ZIP 형식 아카이브입니다. wheel에는 하나의 배포 패키지가 특정 설치 체계를 사용하여 PEP 376에 따라 설치될 때와 거의 같은 형태로 들어 있습니다. 단순한 wheel은 sys.path에 압축을 풀어 바로 사용할 수 있지만, 보통 wheel은 전용 설치 프로그램으로 설치합니다.
이 버전의 wheel 명세는 배포 패키지를 여러 디렉터리에 나누어 설치하는 기능을 추가하고, 설치된 뒤 해당 파일을 찾는 방법도 추가합니다.
PEP 보류
현재 Python 패키징 개선 작업은 추가 사용 사례를 지원하도록 바이너리 아카이브 형식을 확장하는 것보다 패키지 빌드 과정에 집중하고 있으므로, 이 PEP는 현재 적극적으로 추진되지 않고 있습니다.
향후 이 PEP에 대한 작업을 재개할 때 다루어야 할 구체적인 사항은 다음과 같습니다.
- 공식 wheel 형식 정의를 https://packaging.python.org/specifications/ 로 옮기기(PEP 566이 https://packaging.python.org/specifications/core-metadata/ 에 대해 한 것과 유사하게)
- PEP 427에서 바뀌지 않은 모든 정보를 반복하는 대신, 두 형식 버전 사이의 변경 사항과 그 변경의 근거에 초점을 맞추도록 PEP 자체를 갱신하기
- 이 PEP는 기존 설치 프로그램이 기존 설치 체계 정의를 사용하면서도 명세를 준수할 수 있도록 의도적으로 작성되었으며, 동시에 바이너리 아카이브 내용을 더 풍부하게 분류하는 체계를 활용하는 새 설치 체계 정의도 만들 수 있게 한다는 점을 명확히 하기
근거
Wheel 1.0은 site-packages와 distutils가 지정한 몇몇 다른 위치에 파일을 설치하는 데 가장 적합하지만, 사용자는 하나의 배포 패키지에 든 파일을 여러 디렉터리에 설치하기를 원합니다. 예를 들어 문서, 데이터, 코드를 각각 별도의 위치에 설치하려 할 수 있습니다. 안타깝게도 이러한 설치 위치가 루트 디렉터리를 기준으로 어디에 있어야 하는지에 대해 모두가 동의하지는 않습니다. 이 버전의 형식은 훨씬 더 많은 범주를 추가하며, 각 범주는 정책에 따라 서로 다른 위치에 설치될 수 있습니다. 런타임에 설치된 파일을 찾는 것도 중요할 수 있으므로, 이 버전의 형식은 설치된 소프트웨어가 읽을 수 있는 방식으로 설치 경로를 기록하는 방법도 추가합니다.
세부 사항
wheel ‘distribution-1.0-py32-none-any.whl’ 설치하기
wheel 설치는 개념적으로 두 단계로 이루어집니다.
- 압축 풀기.
distribution-1.0.dist-info/WHEEL을 파싱합니다.- 설치 프로그램이 Wheel-Version과 호환되는지 확인합니다. 마이너 버전이 더 높으면 경고하고, 메이저 버전이 더 높으면 중단합니다.
- Root-Is-Purelib == ‘true’이면 아카이브를 purelib(site-packages 패키지 디렉터리)에 풉니다.
- 그렇지 않으면 아카이브를 platlib(site-packages 패키지 디렉터리)에 풉니다.
- 분산 배치.
- 풀린 아카이브에는
distribution-1.0.dist-info/와 (데이터가 있다면)distribution-1.0.data/가 포함됩니다. distribution-1.0.data/의 각 하위 트리를 해당 대상 경로로 옮깁니다.distribution-1.0.data/의 각 하위 디렉터리는distribution-1.0.data/(purelib|platlib|headers|scripts|data)와 같이 대상 디렉터리 딕셔너리의 키입니다.#!python으로 시작하는 스크립트가 올바른 인터프리터를 가리키도록 갱신합니다. (참고: 파이썬 스크립트는 보통 패키지 메타데이터로 처리되며, wheel에 원문 그대로 포함되지 않습니다.)- 설치된 경로로
distribution-1.0.dist.info/RECORD를 갱신합니다. - 비어 있으면
distribution-1.0.data디렉터리를 제거합니다. - 설치된 모든 .py를 .pyc로 컴파일합니다. (제거 프로그램은 RECORD에 언급되지 않은 .pyc도 제거할 수 있을 만큼 영리해야 합니다.)
- 풀린 아카이브에는
실제로 설치 프로그램은 대개 임시 distribution-1.0.data/ 디렉터리를 만들지 않고 아카이브에서 대상 위치로 파일을 직접 추출합니다.
권장 설치 프로그램 기능
#!python재작성.- wheel에서 그대로 포함되는 스크립트는
{distribution}-{version}.data/scripts/에 패키징됩니다.scripts/안에 있는 파일의 첫 줄이 정확히b'#!python'으로 시작하면, 올바른 인터프리터를 가리키도록 다시 작성합니다. 아카이브가 Windows에서 만들어진 경우, Unix 설치 프로그램은 이 파일들에 +x 비트를 추가해야 할 수 있습니다.b'#!pythonw'관례도 허용됩니다.b'#!pythonw'는 콘솔 스크립트가 아닌 GUI 스크립트임을 나타냅니다. - 스크립트 래퍼 생성.
- Python 스크립트는 패키지 메타데이터에서
module:callable문자열로 표현되는 경우가 더 많으며, wheel 아카이브의scripts디렉터리에 그대로 포함되지 않습니다. 이런 종류의 스크립트는 설치 프로그램에 플랫폼별 래퍼를 생성할 기회를 줍니다.
권장 아카이버 기능
.dist-info를 아카이브의 끝에 배치합니다.- 아카이브 도구는
.dist-info파일을 아카이브의 물리적인 끝부분에 배치하는 것이 좋습니다. 이렇게 하면 몇 가지 유용한 ZIP 기법을 쓸 수 있습니다. 예를 들어 아카이브 전체를 다시 쓰지 않고도 메타데이터를 수정할 수 있습니다.
파일 형식
파일 이름 규칙
휠 파일 이름은 {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl입니다.
- 배포판
- 배포판 이름입니다. 예: ‘django’, ‘pyramid’.
- 버전
- 배포판 버전입니다. 예: 1.0.
- 빌드 태그
- 선택 사항인 빌드 번호입니다. 반드시 숫자로 시작해야 합니다. 두 휠의 버전이 같을 때 순서를 정하는 기준입니다. 지정되지 않은 경우에는 빈 문자열로 간주하여 정렬하고, 지정된 경우에는 앞부분의 숫자를 수로 정렬한 뒤 나머지 부분을 사전순으로 정렬합니다.
- 언어 구현 및 버전 태그
- 예: ‘py27’, ‘py2’, ‘py3’.
- ABI 태그
- 예: ‘cp33m’, ‘abi3’, ‘none’.
- 플랫폼 태그
- 예: ‘linux_x86_64’, ‘any’.
예를 들어 distribution-1.0-1-py27-none-any.whl은 ‘distribution’(배포)이라는 패키지의 첫 번째 빌드이며, Python 2.7(모든 Python 2.7 구현)과 호환되고, ABI가 없으며(순수 Python), 모든 CPU 아키텍처에서 동작합니다.
파일 이름에서 확장자 바로 앞의 마지막 세 구성 요소를 “호환성 태그”라고 합니다. 호환성 태그는 패키지가 요구하는 기본적인 인터프리터 조건을 나타내며, 자세한 내용은 PEP 425에 설명되어 있습니다.
이스케이프와 유니코드
파일 이름의 각 구성 요소는 영숫자가 아닌 문자가 연속된 부분을 밑줄 _로 바꾸어 이스케이프합니다:
re.sub("[^\w\d.]+", "_", distribution, re.UNICODE)
아카이브 파일 이름은 유니코드입니다. 패키징 도구는 ASCII 패키지 이름만 지원할 수도 있지만, 이 명세는 유니코드 파일 이름을 지원합니다.
아카이브 내부의 파일 이름은 UTF-8로 인코딩됩니다. 널리 쓰이는 일부 ZIP 클라이언트는 UTF-8 파일 이름을 제대로 표시하지 못하지만, 이 인코딩은 ZIP 명세와 Python의 zipfile에서 모두 지원됩니다.
파일 내용
wheel 파일의 내용은 다음과 같이 구성됩니다. 여기서 {distribution}(배포 이름)은 패키지 이름(예: beaglevote)으로, {version}은 그 버전(예: 1.0.0)으로 대체됩니다.
- 아카이브의 루트인
/에는WHEEL에 지정된 대로purelib또는platlib에 설치될 모든 파일이 들어 있습니다.purelib과platlib은 보통 둘 다site-packages입니다. {distribution}-{version}.dist-info/에는 메타데이터가 들어 있습니다.{distribution}-{version}.data/는 아직 다루지 않은 비어 있지 않은 설치 스킴 키마다 하위 디렉터리를 하나씩 포함합니다. 하위 디렉터리 이름은 설치 경로 딕셔너리의 인덱스입니다(예:data,scripts,include,purelib,platlib).- 설치 시 스크립트 래퍼 생성과
#!python재작성을 적용받으려면 파이썬 스크립트는scripts에 있어야 하며 정확히b'#!python'으로 시작해야 합니다. 스크립트의 확장자는 어떤 것이든 상관없으며, 확장자가 없어도 됩니다. {distribution}-{version}.dist-info/METADATA는 메타데이터 버전 1.1 이상 형식의 메타데이터입니다.{distribution}-{version}.dist-info/WHEEL은 같은 기본 key: value 형식으로 된, 아카이브 자체에 대한 메타데이터입니다:Wheel-Version: 1.9 Generator: bdist_wheel 1.9 Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any Build: 1 Install-Paths-To: wheel/_paths.py Install-Paths-To: wheel/_paths.json
Wheel-Version은 Wheel 명세의 버전 번호입니다.Generator는 아카이브를 생성한 소프트웨어의 이름이며, 선택적으로 그 버전도 포함합니다.Root-Is-Purelib은 아카이브의 최상위 디렉터리를 purelib에 설치해야 하면 true입니다. 그렇지 않으면 루트를 platlib에 설치해야 합니다.Tag는 휠의 확장된 호환성 태그입니다. 예시에서는 파일 이름에py2.py3-none-any가 포함됩니다.Build는 빌드 번호이며, 빌드 번호가 없으면 생략합니다.Install-Paths-To는 아카이브에 상대적인 위치이며, 이 위치는 설치 스킴의 각 범주에 대한 설치 시점 경로로 덮어쓰입니다. 설치 경로 섹션을 참조하십시오. 0번 이상 나타날 수 있습니다.- 휠 설치 프로그램은 Wheel-Version이 자신이 지원하는 버전보다 높으면 경고해야 하며, Wheel-Version의 메이저 버전이 자신이 지원하는 버전보다 높으면 반드시 실패해야 합니다.
- Wheel은 여러 Python 버전에서 동작하도록 만들어진 설치 형식이므로 일반적으로 .pyc 파일을 포함하지 않습니다.
- Wheel은 setup.py나 setup.cfg를 포함하지 않습니다.
.dist-info 디렉터리
- Wheel의 .dist-info 디렉터리에는 최소한 METADATA(메타데이터), WHEEL, RECORD가 포함됩니다.
- METADATA는 패키지 메타데이터이며, sdist의 루트에 있는 PKG-INFO와 같은 형식입니다.
- WHEEL은 패키지의 특정 빌드에 해당하는 휠 메타데이터입니다.
- RECORD는 휠에 포함된 (거의) 모든 파일과 그 보안 해시의 목록입니다. PEP 376과 달리, 자기 자신의 해시를 포함할 수 없는 RECORD를 제외한 모든 파일은 반드시 해시를 포함해야 합니다. 해시 알고리즘은 sha256 이상이어야 합니다. 구체적으로 md5와 sha1은 허용되지 않습니다. 서명된 wheel 파일은 아카이브의 무결성을 검증하는 데 RECORD에 있는 강력한 해시를 사용하기 때문입니다.
- PEP 376의 INSTALLER(설치 프로그램)와 REQUESTED는 아카이브에 포함되지 않습니다.
- RECORD.jws는 디지털 서명에 사용됩니다. 이 파일은 RECORD에 기재되지 않습니다.
- S/MIME 서명으로 wheel 파일을 보호하려는 사람들을 배려하여 RECORD.p7s를 허용합니다. 이 파일은 RECORD에 기재되지 않습니다.
- 압축을 해제하는 동안 휠 설치 프로그램은 RECORD에 있는 모든 해시를 파일 내용과 대조하여 검증합니다. RECORD와 그 서명을 제외하고, 아카이브에 있는 파일 중 하나라도 RECORD에 기재되어 있지 않거나 올바르게 해시되어 있지 않으면 설치는 실패합니다.
.data 디렉터리
일반적으로 site-packages 패키지 디렉터리 안에 설치되지 않는 파일은 모두 .data 디렉터리에 들어갑니다. 이 디렉터리의 이름은 .dist-info 디렉터리와 같지만 확장자가 .data/입니다.:
distribution-1.0.dist-info/
distribution-1.0.data/
.data 디렉터리에는 배포 패키지의 스크립트, 헤더, 문서 등이 담긴 하위 디렉터리가 들어 있습니다. 설치 중에 이 하위 디렉터리의 내용은 각각의 대상 경로로 옮겨집니다.
설치 스킴에 해당 하위 디렉터리가 없으면 설치 프로그램은 경고를 출력해야 하며, 표준 unzip 도구로 패키지의 압축을 푼 것처럼 distribution-1.0.data/...에 설치해야 합니다.
설치 경로
이제 wheel에는 distutils 설치 경로 외에도 GNU autotools를 기반으로 한 아래 범주들이 포함됩니다. 이렇게 확장된 스킴은 설치 프로그램이 시스템 정책을 구현하는 데 도움이 되지만, 설치 프로그램은 각 범주의 루트를 어느 위치에든 둘 수 있습니다.
UNIX 설치 스킴은 다음과 같이 범주를 설치 경로에 매핑할 수 있습니다.:
{
'bindir': '$eprefix/bin',
'sbindir': '$eprefix/sbin',
'libexecdir': '$eprefix/libexec',
'sysconfdir': '$prefix/etc',
'sharedstatedir': '$prefix/com',
'localstatedir': '$prefix/var',
'libdir': '$eprefix/lib',
'static_libdir': r'$prefix/lib',
'includedir': '$prefix/include',
'datarootdir': '$prefix/share',
'datadir': '$datarootdir',
'mandir': '$datarootdir/man',
'infodir': '$datarootdir/info',
'localedir': '$datarootdir/locale',
'docdir': '$datarootdir/doc/$dist_name',
'htmldir': '$docdir',
'dvidir': '$docdir',
'psdir': '$docdir',
'pdfdir': '$docdir',
'pkgdatadir': '$datadir/$dist_name'
}
패키지가 런타임에 자신의 파일을 찾아야 하는 경우, 설치 프로그램이 경로를 지정된 하나 이상의 파일에 기록하도록 요청할 수 있으며, 그 경로는 아카이브 안에 있는 같은 파일에도 아카이브 내 위치에 대한 상대 경로로 함께 포함됩니다(따라서 wheel을 표준 unzip 도구로 풀거나 아예 풀지 않더라도 여전히 올바르게 설치됩니다).
WHEEL 메타데이터에 다음 필드가 들어 있으면:
Install-Paths-To: wheel/_paths.py
Install-Paths-To: wheel/_paths.json
wheel 설치 프로그램은 아카이브에서 wheel/_paths.py를 풀려고 할 때 이 파일을 설치 시점에 실제로 사용되는 경로로 대체합니다. 경로는 절대 경로일 수도 있고, 생성된 파일에 대한 상대 경로일 수도 있습니다.
파일 이름이 .py로 끝나면 Python 스크립트가 기록됩니다. 경로를 얻으려면 이 스크립트를 반드시 실행해야 하지만, 스크립트는 대체로 다음과 같은 모습일 것입니다.:
data='../wheel-0.26.0.dev1.data/data'
headers='../wheel-0.26.0.dev1.data/headers'
platlib='../wheel-0.26.0.dev1.data/platlib'
purelib='../wheel-0.26.0.dev1.data/purelib'
scripts='../wheel-0.26.0.dev1.data/scripts'
# ...
파일 이름이 .json으로 끝나면 JSON 문서가 기록됩니다.:
{ "data": "../wheel-0.26.0.dev1.data/data", ... }
이 파일에는 해당 wheel이 실제로 사용하는 범주만 기록해야 합니다.
이 파일들은 패키징 라이브러리에 대한 의존성을 전혀 만들지 않고도 설치된 패키지가 찾을 수 있는 위치에 기록되도록 설계되었습니다.
서명된 wheel 파일
wheel 파일에는 디지털 서명을 가능하게 하는 확장된 RECORD가 포함됩니다. PEP 376의 RECORD는 두 번째 열에 md5sum 대신 보안 해시 digestname=urlsafe_b64encode_nopad(digest) (끝에 = 문자가 붙지 않는 urlsafe base64 인코딩)를 담도록 변경되었습니다. .pyc 파일처럼 생성된 파일을 포함해 가능한 모든 항목의 해시를 계산하지만, 자기 자신의 해시를 담을 수 없는 RECORD는 제외합니다. 예를 들면 다음과 같습니다.:
file.py,sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\_pNh2yI,3144
distribution-1.0.dist-info/RECORD,,
서명 파일 RECORD.jws와 RECORD.p7s는 RECORD가 생성된 뒤에야 추가할 수 있으므로 RECORD에 전혀 언급되지 않습니다. 아카이브의 다른 모든 파일은 RECORD에 올바른 해시가 있어야 하며, 그렇지 않으면 설치가 실패합니다.
JSON 웹 서명을 사용하는 경우, 하나 이상의 JSON Web Signature JSON Serialization(JWS-JS) 서명이 RECORD 옆의 RECORD.jws 파일에 저장됩니다. JWS는 RECORD의 SHA-256 해시를 서명의 JSON 페이로드로 포함하는 방식으로 RECORD에 서명하는 데 사용됩니다.:
{ "hash": "sha256=ADD-r2urObZHcxBW3Cr-vDCu5RJwT4CaRTHiFmbcIYY" }
(해시 값은 RECORD에서 사용하는 것과 같은 형식입니다.)
RECORD.p7s를 사용하는 경우, 이 파일에는 RECORD에 대한 분리된(detached) S/MIME 형식 서명이 들어 있어야 합니다.
wheel 설치 프로그램이 디지털 서명을 이해할 필요는 없지만, RECORD에 있는 해시를 추출된 파일 내용과 대조하여 반드시 검증해야 합니다. 설치 프로그램이 파일 해시를 RECORD와 대조하여 검사할 때, 별도의 서명 검사기는 RECORD가 서명과 일치하는지만 확인하면 됩니다.
다음을 참조하십시오.
.egg와의 비교
- Wheel은 설치 형식이고, egg는 임포트할 수 있는 형식입니다. Wheel 아카이브는 .pyc를 포함하지 않아도 되며, 특정 Python 버전이나 구현에 덜 묶여 있습니다. Wheel은 이전 버전의 Python으로 빌드된 (순수 Python) 패키지를 설치할 수 있으므로, 패키저가 따라잡을 때까지 매번 기다리지 않아도 됩니다.
- Wheel은 .dist-info 디렉터리를 사용하고, egg는 .egg-info를 사용합니다. Wheel은 새로운 Python 패키징 체계 및 그와 함께 등장한 새로운 개념과 호환됩니다.
- Wheel은 여러 구현이 공존하는 오늘날의 환경에 맞게 더 풍부한 파일 명명 규칙을 갖추고 있습니다. 하나의 wheel 아카이브로 여러 Python 언어 버전과 구현, ABI, 시스템 아키텍처와의 호환성을 나타낼 수 있습니다. 역사적으로 ABI는 CPython 릴리스마다 고유했지만, wheel은 안정 ABI를 맞이할 준비가 되어 있습니다.
- Wheel은 무손실입니다. 최초의 wheel 구현인 bdist_wheel은 항상 egg-info를 먼저 생성한 다음 이를 .whl로 변환합니다. 기존의 egg와 bdist_wininst 배포판을 변환할 수도 있습니다.
- Wheel에는 버전이 있습니다. 모든 wheel 파일에는 wheel 명세의 버전과 해당 파일을 패키징한 구현이 기록되어 있습니다. 다음 마이그레이션은 그저 Wheel 2.0으로 옮겨 가는 것으로 끝나기를 바랍니다.
- Wheel이라는 이름은 또 다른 Python을 가리키는 말입니다.
FAQ
Wheel은 .data 디렉터리를 정의합니다. 모든 데이터를 그곳에 넣어야 합니까?
이 명세는 코드를 어떻게 구성해야 하는지에 대해 특별한 입장을 취하지 않습니다. .data 디렉터리는 보통site-packages안이나 PYTHONPATH에 설치되지 않는 파일들을 위한 장소일 뿐입니다. 다시 말해, 그러한 파일들이 보통 wheel의.data디렉터리로 배포되지 않더라도pkgutil.get_data(package, resource)를 계속 사용해도 됩니다.
wheel은 왜 첨부 서명을 포함합니까?
첨부 서명은 아카이브와 함께 이동하므로 분리 서명보다 편리합니다. 개별 파일만 서명되므로, 서명을 무효화하지 않고 아카이브를 다시 압축할 수 있고, 전체 아카이브를 내려받지 않고도 개별 파일을 검증할 수 있습니다.
wheel은 왜 JWS 서명을 허용합니까?
JWS가 속한 JOSE 명세들은 구현하기 쉽도록 설계되었으며, 이는 wheel의 주요 설계 목표 중 하나이기도 합니다. JWS를 사용하면 유용하고 간결한 순수 Python 구현을 만들 수 있습니다.
wheel은 왜 S/MIME 서명도 허용합니까?
S/MIME 서명은 기존 공개 키 인프라를 wheel과 함께 사용해야 하거나 사용하고 싶은 사용자를 위해 허용됩니다.서명된 패키지는 안전한 패키지 업데이트 시스템의 기본 구성 요소에 불과합니다. Wheel은 그 구성 요소만을 제공합니다.
“purelib”와 “platlib”의 차이는 무엇입니까?
Wheel은 “purelib”와 “platlib”의 구분을 유지하며, 이 구분은 일부 플랫폼에서 중요한 의미를 갖습니다. 예를 들어, Fedora는 순수 Python 패키지를 ‘/usr/lib/pythonX.Y/site-packages’에 설치하고 플랫폼 의존 패키지를 ‘/usr/lib64/pythonX.Y/site-packages’에 설치합니다.모든 파일이
{name}-{version}.data/purelib에 있는 “Root-Is-Purelib: false” wheel은 같은 파일들이 루트에 있는 “Root-Is-Purelib: true” wheel과 동등하며, “purelib”와 “platlib” 두 범주 모두에 파일을 두는 것도 허용됩니다.실제로는 wheel이 순수 Python인지 여부에 따라 “purelib”나 “platlib” 중 하나만 가져야 하며, 해당 파일들은 “Root-is-purelib”에 적절한 설정을 지정한 상태로 루트에 있어야 합니다.
wheel 파일에서 Python 코드를 직접 임포트할 수 있습니까?
기술적으로는, 단순 압축 해제를 통한 설치를 지원한다는 점과zipimport과 호환되는 아카이브 형식을 사용한다는 점이 결합되어, 일부 wheel 파일은sys.path에 직접 두는 것을 실제로 지원합니다. 그러나 이 동작은 형식 설계의 자연스러운 결과이기는 하지만, 실제로 이에 의존하는 것은 일반적으로 권장되지 않습니다.첫째, wheel은 본래 배포 형식으로 설계되었으므로, 설치 단계를 건너뛴다는 것은 완전한 설치를 전제로 하는 기능(예:
pip과virtualenv같은 표준 도구를 사용하여 감사 및 보안 업데이트 목적으로 제대로 추적할 수 있는 방식으로 의존성을 파악하고 관리하는 것, 또는 헤더 파일을 적절한 위치에 게시하여 C 확장을 위한 표준 빌드 체계와 완전히 통합하는 것)에 대한 의존을 의도적으로 포기한다는 의미이기도 합니다.둘째, 일부 Python 소프트웨어는 zip 아카이브에서 직접 실행할 수 있도록 작성되지만, 완전히 설치되었다고 가정하고 작성된 코드도 여전히 흔합니다. zip 아카이브에서 소프트웨어를 실행하려고 하여 그 가정이 깨지면, 발생하는 실패는 모호하고 진단하기 어려운 경우가 많습니다(특히 서드파티 라이브러리에서 발생하는 경우 그렇습니다). 이와 관련된 가장 흔한 두 가지 문제의 원인은, CPython이 zip 아카이브에서 C 확장을 임포트하는 것을 지원하지 않는다는 점(어떤 플랫폼에서도 동적 로딩 체계가 이를 직접 지원하지 않기 때문입니다)과, zip 아카이브에서 실행할 때
__file__속성이 더 이상 일반적인 파일 시스템 경로를 가리키지 않고 파일 시스템상의 zip 아카이브 위치와 아카이브 내부 모듈의 상대 경로를 모두 포함하는 결합 경로를 가리킨다는 점입니다. 소프트웨어가 내부적으로 추상 리소스 API를 올바르게 사용하더라도, 외부 구성 요소와 연동하려면 여전히 실제 디스크상의 파일이 필요할 수 있습니다.메타클래스, 몽키패칭, 메타 경로 임포터와 마찬가지로, 이 기능을 활용해야 한다는 확신이 아직 없다면 거의 확실히 필요하지 않습니다. 그래도 이 기능을 정말로 사용하기로 결정했다면, 많은 프로젝트가 실패를 진짜 버그로 받아들이기 전에 완전히 설치된 패키지에서 그 실패를 재현하도록 요구한다는 점에 유의하십시오.
부록
urlsafe-base64-nopad 구현 예시:
# urlsafe-base64-nopad for Python 3
import base64
def urlsafe_b64encode_nopad(data):
return base64.urlsafe_b64encode(data).rstrip(b'=')
def urlsafe_b64decode_nopad(data):
pad = b'=' * (4 - (len(data) & 3))
return base64.urlsafe_b64decode(data + pad)
Copyright
This document has been placed into the public domain.