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

Python 개선 제안 한국어 번역

PEP 396 – 모듈 버전 번호

Author:
Barry Warsaw <barry at python.org>
Status:
Withdrawn
Type:
Informational
Topic:
Packaging
Created:
16-Mar-2011
Post-History:
05-Apr-2011

Table of Contents

번역·라이선스 안내

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

Important

This PEP has been withdrawn.

×

Python 패키징 사용자 가이드의 Accessing version information at runtimeSingle-sourcing the Project Version을 참조하여 런타임에 패키지 버전 정보에 접근하는 최신 권장 방법과 패키지 배포 메타데이터와 자동으로 일관성을 유지하는 런타임 __version__속성을 정의하는 방법을 확인하십시오.

초록

Python 모듈에 버전 번호를 지정하는 것이 유용하고 일반적이며, 이를 수행하는 다양한 방법이 Python 커뮤니티 안에서 유기적으로 발전해 왔으므로, 모듈 작성자가 따르고 참고할 수 있는 표준 규약을 확립하는 것이 유용합니다. 이 정보 제공 PEP는 Python 모듈의 버전 번호를 정의하려는 Python 모듈 작성자를 위한 모범 사례를 설명합니다.

이 PEP의 준수는 선택 사항이지만, 다른 Python 도구(예: distutils2 [1])는 여기에서 정의한 규약을 사용하도록 조정될 수 있습니다.

PEP 거부/철회

이 PEP는 2021-04-14에 공식적으로 거부되었습니다. 이 PEP가 처음 작성된 이후 그 사이의 기간 동안 패키징 생태계가 크게 변화했으며, importlib.metadata.version() [11]과 같은 API가 훨씬 나은 경험을 제공합니다.

이 거부는 2024-10-21에 철회로 재분류되었습니다. 이전 상태가 no 모듈도 __version__속성을 정의해서는 안 된다는 의미로 잘못 해석되고 있었습니다 [12]. 이는 분명히 사실이 아닙니다.

모듈은 원하는 경우 여전히 __version__을 자유롭게 정의할 수 있습니다. 그러나 그렇게 하지 않는 것을 선택하더라도 설치된 배포 패키지의 버전 정보를 조회하는 데 방해가 되지 않으므로, Informational PEP는 모듈 __version__ 특성 사용에 관한 커뮤니티 관례를 문서화하기에 적절한 도구가 아닙니다(이는 Python Packaging User Guide의 일부로 다루는 편이 더 적절합니다).

사용자 사례

Alice는 다른 Python 개발자와 공유하려는 alice라는 새 모듈을 작성하고 있습니다. alice는 간단한 모듈이며 alice.py라는 하나의 파일에 들어 있습니다. Alice는 사용자가 자신이 어떤 버전을 사용하고 있는지 알 수 있도록 버전 번호를 지정하려고 합니다. 모듈이 전부 하나의 파일에 들어 있으므로, Alice는 해당 파일에 버전 번호를 추가하려고 합니다.

Bob은 여러 사용자와 공유해 온 bob이라는 모듈을 작성했습니다. bob.py에는 사용자의 편의를 위해 버전 번호가 들어 있습니다. Bob은 Cheeseshop [2]에 대해 알게 되었고, The Bob Bundle을 Cheeseshop에 업로드할 수 있도록 클래식 distutils를 사용해 간단한 패키징을 추가합니다. bob.py는 사용자가 프로그래밍 방식으로 접근할 수 있는 버전 번호를 이미 지정하고 있으므로, 이제 사용자가 Cheeseshop에서 이를 받게 되더라도 동일한 API가 계속 작동하기를 원합니다.

Carol은 여러 네임스페이스 패키지를 유지 관리하며, 각 패키지는 독립적으로 개발되고 배포됩니다. 사용자가 자신의 패키지에 적절한 버전에 대한 의존성을 올바르게 지정할 수 있도록, Carol은 네임스페이스 패키지의 setup.py파일에 버전 번호를 지정합니다. Carol은 패키지마다 하나의 버전 번호만 업데이트하고 싶으므로, 모듈에 버전 번호를 지정하고 sdist 아카이브를 빌드할 때 setup.py가 모듈 버전 번호를 추출하도록 합니다.

David은 표준 라이브러리의 패키지를 유지 관리하며, 다른 Python 버전을 위한 독립 실행형 버전도 제작합니다. 표준 라이브러리 사본은 모듈에 버전 번호를 정의하며, 이와 동일한 버전 번호가 독립 실행형 배포판에도 사용됩니다.

근거

표준 라이브러리에 포함되거나 서드 파티에서 제공되는 Python 모듈에는 오래전부터 버전 번호가 포함되어 왔습니다. 버전 번호를 설명하는 확립된 사실상의 표준이 있으며, 여러 임의적인 방법도 수년에 걸쳐 유기적으로 발전해 왔습니다. 흔히 모듈을 가져온 후 속성을 검사하여 모듈에서 프로그래밍 방식으로 버전 번호를 가져올 수 있습니다. 클래식 Python distutils의 setup()함수 [3]는 릴리스의 버전 번호를 지정할 수 있는 version 인자를 설명합니다. PEP 8에서는 키워드 확장을 사용하여 “Subversion, CVS, 또는 RCS” 버전 문자열을 기록하기 위해 __version__이라는 모듈 속성을 사용하는 방법을 설명합니다. PEP 작성자 본인의 이메일 보관 기록에서 독립적인 모듈 개발자가 __version__모듈 속성을 사용한 가장 이른 사례는 1995년으로 거슬러 올라갑니다.

버전 정보의 또 다른 예로는 sqlite_version_info, version, version_info 속성을 가진 sqlite3 [5] 모듈이 있습니다. 어떤 속성이 모듈의 버전 번호를 포함하고 어떤 속성이 기반 SQLite3 라이브러리의 버전 번호를 포함하는지는 즉시 명확하지 않을 수 있습니다.

이 정보 제공 PEP는 확립된 관행을 성문화하고, 모듈 버전 번호를 설명하는 표준 방법과 버전 번호를 포함할 경우 및 포함하지 not 않을 경우의 일부 사용 사례를 권장합니다. 모듈 작성자가 이를 채택하는 것은 전적으로 자발적이며, 표준 라이브러리의 패키징 도구는 여기에 정의된 표준을 선택적으로 지원하고 Python 생태계의 다른 도구도 이를 준수할 수 있습니다.

사양

  1. 일반적으로 표준 라이브러리의 모듈은 버전 번호를 가져서는 안 됩니다. 표준 라이브러리 모듈은 암묵적으로 자신이 포함된 Python 릴리스의 버전 번호를 가집니다.
  2. 경우에 따라 다른 Python 버전을 위한 독립 실행형 형태로도 릴리스되는 표준 라이브러리 모듈은 표준 라이브러리에 포함될 때 모듈 버전 번호를 포함할 수 있으며, 별도로 패키징할 때는 버전 번호를 포함해야 합니다.
  3. 모듈(또는 패키지)에 버전 번호가 포함되는 경우, 해당 버전은 __version__속성에서 사용할 수 있어야 합니다.
  4. 네임스페이스 패키지 내부에 있는 모듈의 경우, 해당 모듈은 __version__속성을 포함해야 합니다. 네임스페이스 패키지 자체는 고유한 __version__속성을 포함해서는 안 됩니다.
  5. __version__속성의 값은 문자열이어야 합니다.
  6. 모듈 버전 번호는 PEP 386에 지정된 정규화된 버전 형식을 따라야 합니다.
  7. 모듈 버전 번호에는 버전 관리 시스템이 제공하는 수정 번호나 의미상 다른 버전 번호(예: 기반 라이브러리 버전 번호)가 포함되어서는 안 됩니다.
  8. 클래식 distutils setup.py파일의 version 속성 또는 PEP 345Version 메타데이터 필드는 __version__필드에서 파생되거나 그 반대여야 합니다.

서드 파티 패키지에서 버전 번호 가져오기:

>>> import bzrlib
>>> bzrlib.__version__
'2.3.0'

독립 실행형 모듈로도 배포되는 표준 라이브러리 패키지에서 버전 번호 가져오기:

>>> import email
>>> email.__version__
'5.1.0'

네임스페이스 패키지의 버전 번호:

>>> import flufl.i18n
>>> import flufl.enum
>>> import flufl.lock

>>> print flufl.i18n.__version__
1.0.4
>>> print flufl.enum.__version__
3.1
>>> print flufl.lock.__version__
2.1

>>> import flufl
>>> flufl.__version__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '__version__'
>>>

파생

모듈 버전 번호는 최소 두 곳, 때로는 그 이상에 나타날 수 있습니다. 예를 들어 이 PEP에 따라 모듈의 __version__속성에서 프로그래밍 방식으로 사용할 수 있습니다. 클래식 distutils setup.py파일에서 setup() 함수는 version 인자를 받으며, distutils2 setup.cfg 파일에는 version 키가 있습니다. 버전 번호는 PEP 345 메타데이터에도 포함되어야 하며, sdist 아카이브를 빌드할 때 포함하는 것이 가장 좋습니다. 모듈 작성자가 버전 번호를 한 번만 지정하고 다른 모든 사용처가 이 단일 정의에서 파생되도록 하는 것이 바람직합니다.

이는 여러 방법으로 수행할 수 있으며, 그중 몇 가지를 아래에 설명합니다. 다음 내용은 설명을 위한 것일 뿐이며, 확정적이거나 완전하거나 모든 경우를 포괄하도록 의도된 것은 아닙니다. 다른 접근법도 가능하며, 아래에 포함된 일부 방법은 특정 상황에서 사용하지 못하게 하는 제한이 있을 수 있습니다.

Elle이 자신의 모듈 파일 elle.py에 다음 속성을 추가한다고 가정하십시오.:

__version__ = '3.1.1'

클래식 distutils

클래식 distutils에서 setup.pysetup() 함수에 버전 문자열을 추가하는 가장 간단한 방법은 다음과 같이 하는 것입니다.:

from elle import __version__
setup(name='elle', version=__version__)

그러나 PEP 작성자의 경험에 따르면, 모듈이 2to3 프로그램을 통한 Python 3 자동 변환을 사용하는 경우처럼 일부 상황에서는 이 방법이 실패할 수 있습니다(elle 모듈이 변환되기 전에 Python 3가 setup.py를 실행하기 때문입니다).

이 경우, __version__을 임포트하는 대신 파일에서 파싱하는 코드를 작성하는 것이 그리 어렵지는 않습니다. 자세히 설명하지는 않겠지만, distutils2 같은 모듈이 파일에서 버전 문자열을 파싱하는 방법을 제공할 가능성이 높습니다. 예를 들면:

from distutils2 import get_version
setup(name='elle', version=get_version('elle.py'))

Distutils2

distutils2 스타일의 setup.cfg는 선언적이기 때문에, 임포트를 통해서든 파싱을 통해서든 __version__ 속성을 추출하기 위한 어떤 코드도 실행할 수 없습니다.

distutils-sig [9]와 협의하여 두 가지 방법이 제안되었습니다. 두 방법 모두 버전 번호를 파일에 담고, 그 파일을 setup.cfg에 선언하는 것을 전제로 합니다. 파일의 전체 내용이 버전 번호로 이루어진 경우, version-file 키가 사용됩니다:

[metadata]
version-file: version.txt

버전 번호가 예를 들어 Python 코드처럼 더 큰 파일 안에 포함되어 있어 버전을 추출하려면 파일을 파싱해야 하는 경우, version-from-file 키가 사용됩니다:

[metadata]
version-from-file: elle.py

위에서 설명한 것과 유사한 파싱 방법이 콜론 뒤에 명명된 파일에 대해 수행됩니다. 이를 수행하는 정확한 방법은 해당 distutils2 개발 포럼에서 논의될 것입니다.

다른 방법으로는 setup.cfg에만 버전 번호를 정의하고 pkgutil 모듈 [8]을 사용해 프로그램적으로 접근할 수 있게 만드는 것입니다. 예를 들어 elle.py에서:

from distutils2._backport import pkgutil
__version__ = pkgutil.get_distribution('elle').metadata['version']

PEP 376 메타데이터

PEP 376은 정적 메타데이터를 위한 표준을 정의하지만, 이 메타데이터가 생성되는 과정은 설명하지 않습니다. 파생된 버전 정보는 설치 시점이 아니라 빌드 시점에 PEP 376 .dist-info 메타데이터에 포함되는 것이 매우 바람직합니다. 이렇게 하면 코드가 설치되어 있지 않더라도 메타데이터를 인트로스펙션할 수 있게 됩니다.

참고 문헌