PEP 262 – 설치된 Python 패키지의 데이터베이스
- Author:
- A.M. Kuchling <amk at amk.ca>
- Status:
- Rejected
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 08-Jul-2001
- Post-History:
- 27-Mar-2002
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
소개
이 PEP는 시스템에 설치된 Python 소프트웨어의 데이터베이스 형식을 기술합니다.
(이 문서에서 “배포판(distribution)”이라는 용어는 함께 개발되고 배포되는 코드의 집합을 뜻합니다. “배포판”은 Red Hat이나 Debian 패키지와 같은 것이지만, “패키지”라는 용어는 Python 용어에서 이미 “__init__.py 파일이 들어 있는 디렉터리”라는 의미를 가지고 있습니다.)
요구 사항
시스템에 어떤 배포판이 설치되어 있는지, 그리고 그 배포판의 어떤 버전이 설치되어 있는지 알아낼 방법이 필요합니다. CPAN, APT, RPM과 유사한 기능을 제공하고자 합니다. 지원해야 하는 필수 사용 사례는 다음과 같습니다.
- 배포판 X가 시스템에 있습니까?
- 배포판 X의 어떤 버전이 설치되어 있습니까?
- 배포판 X의 새 버전은 어디에서 찾을 수 있습니까? (이는 “사용자가 방문하여 다운로드 링크를 찾을 수 있는 홈페이지” 또는 “프로그램이 최신 버전을 찾을 수 있는 장소” 중 하나로 정의할 수 있습니다. 아마 둘 다 지원해야 할 것입니다.)
- 배포판 X는 내 시스템에 어떤 파일을 설치했습니까?
- x/y/z.py 파일은 어떤 배포판에서 왔습니까?
- 누군가 x/y/z.py를 로컬에서 수정했습니까?
- 이 소프트웨어는 어떤 다른 배포판을 필요로 합니까?
- 이 배포판은 어떤 Python 모듈을 제공합니까?
데이터베이스 위치
데이터베이스는 <prefix>/lib/python<version>/install-db/ 아래의 여러 파일에 저장됩니다. 이 PEP의 나머지 부분에서는 이 위치를 INSTALLDB라고 부릅니다.
데이터베이스의 구조는 의도적으로 단순하게 유지됩니다. 이 디렉터리 또는 (있다면) 그 하위 디렉터리의 각 파일은 하나의 배포판을 기술합니다. 그러면 RPM 같은 Python 소프트웨어의 바이너리 패키징은 해당 파일을 INSTALLDB 디렉터리에 설치하기만 하면 Python의 데이터베이스를 갱신할 수 있습니다.
하위 디렉터리를 탐색하는 근거는, 데이터베이스 디렉터리에 항목이 너무 많아지면 디렉터리 기반 색인 방식으로 옮겨 갈 수 있다는 점입니다. 예를 들어, 이를 통해 INSTALLDB/Numeric에서 INSTALLDB/N/Nu/Numeric 또는 이와 유사한 해싱 방식으로 투명하게 전환할 수 있습니다.
데이터베이스 내용
INSTALLDB 또는 그 하위 디렉터리의 각 파일은 하나의 배포판을 기술하며, 다음과 같은 내용을 담고 있습니다.
첫 줄에는 이 파일에 있는 섹션들이 공백으로 구분되어 나열됩니다. 현재 이 줄은 항상 ‘PKG-INFO FILES REQUIRES PROVIDES’입니다. 이는 향후 확장에 대비하기 위한 것입니다. 예를 들어 문서 파일을 나열하기 위한 새 섹션을 추가한다면, DOCS 섹션을 추가하고 이를 내용 목록에 나열하게 됩니다. 섹션들은 항상 빈 줄로 구분됩니다.
설치에 Distutils를 사용하는 배포판은 데이터베이스를 자동으로 갱신해야 합니다. 자체 설치 방식을 사용하는 배포판은 데이터베이스의 API를 사용하여 자신의 항목을 직접 추가하거나 갱신해야 합니다. RPM이나 pkgadd 같은 시스템 패키지 관리자는 INSTALLDB 디렉터리에 새 파일을 만들기만 하면 됩니다.
파일의 각 섹션은 서로 다른 용도로 사용됩니다.
PKG-INFO 섹션
PEP 241 “Python 소프트웨어 패키지를 위한 메타데이터”에 설명된 대로, 파일의 배포 정보를 담은 RFC 822 헤더의 초기 집합입니다.
FILES 섹션
배포판이 설치한 각 파일에 대한 항목입니다. 배포판이 설치한 원본 .py 파일뿐 아니라 .pyc 및 .pyo 파일 같은 생성된 파일도 이 목록에 포함됩니다. 다만 생성된 파일의 체크섬은 저장하거나 검사하지 않습니다.
각 파일의 항목은 탭으로 구분된 한 줄이며, 다음 필드를 포함합니다:
- 시스템에 설치된 파일의 전체 경로입니다.
- 파일의 크기
- 파일의 권한입니다. Windows에서는 이 필드가 항상 ‘unknown’입니다.
- 파일의 소유자와 그룹이며, 탭으로 구분됩니다. Windows에서는 이 두 필드가 모두 ‘unknown’입니다.
- 파일의 SHA1 다이제스트이며, 16진수로 인코딩됩니다. *.pyc 파일 같은 생성된 파일의 경우 이 필드에는 반드시 문자열 “-“가 들어가야 하며, 이는 해당 파일의 체크섬을 검증하지 않아야 함을 나타냅니다.
REQUIRES 섹션
이 섹션은 이 모듈 배포판이 제대로 실행되는 데 필요한 서비스를 나타내는 문자열의 목록입니다. 이 목록에는 배포 이름(표준 라이브러리를 나타내는 “python-stdlib”)과 모듈 이름(“rfc822”, “htmllib”, “email”, “email.Charset”)이 포함됩니다. 이 목록은 distutils.core.setup() 함수에 추가 인자 ‘requires’를 전달하여 지정합니다. 예를 들면 다음과 같습니다:
setup(..., requires=['xml.utils.iso8601',
언젠가는 모든 코드를 살펴보고 요구 사항 목록을 만들어 내는 자동화 도구가 나올 수도 있지만, 그런 도구가 가능한 모든 경우를 처리할 수 있을 가능성은 낮습니다. 따라서 요구 사항을 직접 지정하는 방법은 항상 필요합니다.
PROVIDES 섹션
이 섹션은 설치된 배포판이 제공하는 서비스를 나타내는 문자열의 목록입니다. 이 목록에는 배포 이름(표준 라이브러리를 나타내는 “python-stdlib”)과 모듈 이름(“rfc822”, “htmllib”, “email”, “email.Charset”)이 포함됩니다.
XXX 파일도 나열해야 합니까? 예를 들어 데이터 파일, 필요한 스크립트 등을 포함하도록 $PREFIX/lib/color-table.txt 같은 파일을 나열하는 것입니다.
언젠가는 모듈 개발자가 이 섹션에 자신만의 문자열을 추가할 수 있는 옵션이 생길 수도 있습니다. 예를 들어 이 섹션에 “XML parser”를 추가하면, 다른 모듈 배포판은 여러 XML 파서 중 어느 것이든 사용할 수 있음을 나타내기 위해 “XML parser”를 의존성 중 하나로 나열할 수 있습니다. 이 기능은 너무 많은 문제를 일으키기 때문에 현재로서는 지원하지 않습니다. 허용되는 문자열의 중앙 레지스트리가 필요할까요, 아니면 사람들이 원하는 것을 아무거나 넣도록 두어야 할까요? 기타 등등…
API 설명
기본이 되는 클래스는 InstallationDatabase 하나뿐입니다. 이 클래스의 코드는 distutils/install_db.py에 있습니다. (XXX 표준 라이브러리 안의 다른 위치나 다른 모듈 이름에 대한 제안이 있습니까?)
InstallationDatabase는 설치된 배포판에 대한 모든 정보를 담은 Distribution 인스턴스를 반환합니다.
XXX Distribution(배포)의 필드 중 몇몇은 distutils.dist.Distribution에 있는 필드와 중복됩니다. 아마도 그 필드들은 여기서 제안하는 Distribution(배포) 클래스로 분리해 내야 하겠지만, 하위 호환성을 유지하는 방식으로 이렇게 할 수 있겠습니까?
InstallationDatabase의 인터페이스는 다음과 같습니다:
class InstallationDatabase:
def __init__ (self, path=None):
"""InstallationDatabase(path:string)
Read the installation database rooted at the specified path.
If path is None, INSTALLDB is used as the default.
"""
def get_distribution (self, distribution_name):
"""get_distribution(distribution_name:string) : Distribution
Get the object corresponding to a single distribution.
"""
def list_distributions (self):
"""list_distributions() : [Distribution]
Return a list of all distributions installed on the system,
enumerated in no particular order.
"""
def find_distribution (self, path):
"""find_file(path:string) : Distribution
Search and return the distribution containing the file 'path'.
Returns None if the file doesn't belong to any distribution
that the InstallationDatabase knows about.
XXX should this work for directories?
"""
class Distribution:
"""Instance attributes:
name : string
Distribution name
files : {string : (size:int, perms:int, owner:string, group:string,
digest:string)}
Dictionary mapping the path of a file installed by this distribution
to information about the file.
The following fields all come from PEP 241.
version : distutils.version.Version
Version of this distribution
platform : [string]
summary : string
description : string
keywords : string
home_page : string
author : string
author_email : string
license : string
"""
def add_file (self, path):
"""add_file(path:string):None
Record the size, ownership, &c., information for an installed file.
XXX as written, this would stat() the file. Should the size/perms/
checksum all be provided as parameters to this method instead?
"""
def has_file (self, path):
"""has_file(path:string) : Boolean
Returns true if the specified path belongs to a file in this
distribution.
"""
def check_file (self, path):
"""check_file(path:string) : Boolean
Checks whether the file's size, checksum, and ownership match,
returning true if they do.
"""
산출물
이 PEP에 추가할 데이터베이스 API 설명입니다.
1) InstallationDatabase 클래스를 구현하고, 2) 새 배포판이 설치될 때 데이터베이스를 갱신하며, 3) 간단한 패키지 관리 도구를 추가하는 Distutils 패치입니다. 이 도구의 기능은 이 PEP에 추가할 예정입니다. (아니면 별도의 PEP로 다뤄야 하겠습니까?) 현재 패치는 [2]를 참조하십시오.
미해결 문제
PJE는 설치 데이터베이스가 “sys.path의 모든 디렉터리에 존재할 수 있고, 그 내용은 sys.path 순서대로 병합되어야 한다고 제안합니다. 이렇게 하면 홈 디렉터리나 다른 대체 위치에 설치하는 방식도 동작할 수 있고, distutils 설치 명령이 파일을 작성하는 과정도 쉬워집니다.” 좋은 기능입니다. 이는 패키지 관리자 도구가 사용자가 개인적으로 설치한 Python 패키지까지 고려할 수 있다는 뜻입니다.
AMK의 의문은 이렇습니다. sys.path에 없는 디렉터리에 패키지를 설치하라는 지시를 받으면 setup.py는 무엇을 합니까? 기록하라고 지시받은 디렉터리에 install-db 디렉터리를 기록합니까, 아니면 아무것도 하지 않습니까?
패키지 데이터베이스 파일 자체도 파일 목록에 포함해야 합니까? (PJE는 그래야 한다고 생각하겠지만, 물론 그 파일은 자기 자신의 체크섬을 담을 수 없습니다. AMK는 DB 파일을 포함하는 것이 중요해지는 사용 사례를 떠올리지 못합니다.)
PJE는 다른 파일을 설치하기 전에 패키지 DB 파일을 먼저 기록하는 방안을 고민하고 있습니다. 그러면 실패한 부분 설치를 되돌릴 수도 있고, 깨진 설치로 인식할 수도 있습니다. 이 PEP에서 이런 상황을 인식하는 알고리즘을 명시해야 할 수도 있습니다.
설치 데이터베이스의 형식이 Python 버전 간에 호환되도록 보장해야 합니까, 아니면 임의로 바뀔 수 있게 해야 합니까? 아마 호환성을 보장해야 할 것입니다.
기각된 제안
배포판마다 텍스트 파일 하나를 쓰는 대신, 큰 텍스트 파일 하나나 anydbm 파일을 사용할 수도 있습니다. 이 방안은 몇 가지 이유로 기각되었습니다. 첫째, 데이터베이스는 소프트웨어를 설치하거나 제거할 때만 사용되고 이는 비교적 드문 작업이므로, 성능은 아마 그다지 시급한 문제가 아닙니다. 확장성도 문제가 되지 않을 가능성이 높습니다. Python 패키지를 수백 개 설치할 수는 있겠지만, 수천 개나 수만 개를 설치할 가능성은 낮아 보이기 때문입니다. 마지막으로, 개별 텍스트 파일은 RPM이나 DPKG 같은 설치 프로그램과 호환됩니다. 바이너리 패키지 작성자가 새 데이터베이스 파일을 데이터베이스 디렉터리에 넣기만 하면 되기 때문입니다. 큰 텍스트 파일 하나나 바이너리 파일을 사용한다면, Python 데이터베이스를 갱신하기 위해 postinstall 스크립트를 실행해야 합니다.
Windows에서는 파일의 권한과 소유자/그룹이 저장되지 않습니다. 사실 Windows도 소유권과 접근 권한을 지원하지만, 이를 읽고 설정하려면 win32all 확장이 필요하며, 이 확장은 Windows용 기본 Python 설치 프로그램에 들어 있지 않습니다.
참고 문헌
[1] Michael Muller의 패치(1999년 12월 28일 무렵 Distutils-SIG에 게시됨)는 설치된 파일 목록을 생성합니다.
감사의 글
이 PEP의 아이디어는 원래 Greg Ward, Fred L. Drake Jr., Thomas Heller, Mats Wichmann, Phillip J. Eby 등이 올린 게시물에서 나왔습니다.
이 문서의 많은 수정과 재작성은 Distutils SIG의 독자들이 제안한 것입니다.
Copyright
This document has been placed in the public domain.