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

Python 개선 제안 한국어 번역

PEP 780 – 환경 마커로서의 ABI 기능

Author:
Klaus Zimmermann <klaus_zimmermann at gmx.de>, Ralf Gommers <ralf.gommers at gmail.com>
Sponsor:
Lysandros Nikolaou <lisandrosnik at gmail.com>
Discussions-To:
Discourse thread
Status:
Draft
Type:
Standards Track
Topic:
Packaging
Created:
21-Mar-2025
Python-Version:
3.14
Post-History:
05-Aug-2024, 26-Mar-2025

Table of Contents

번역·라이선스 안내

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

초록

이 PEP는 새로운 sys_abi_features 환경 마커를 통해 ABI 기능을 프로젝트 의존성의 환경 마커로 사용하는 방법을 정의합니다. PEP 508(나중에 Dependency specifiers로 이동)은 의존성을 언제 사용해야 하는지 기술하는 규칙에 따라 의존성을 지정할 수 있도록 환경 마커를 도입했습니다. 이 PEP는 환경 마커를 확장하여 Python 인터프리터의 특정 ABI 기능에 따라 의존성을 지정할 수 있게 합니다. 이를 위해 ABI Features 집합을 정의하고, 이 기능들이 새 마커 변수인 sys_abi_features로서 환경 마커에 어떻게 제공되는지 규정합니다.

동기

2015년에 PEP 508은 환경 조건에 따라 의존성을 지정할 수 있도록 환경 마커를 확립했습니다. 자유 스레드 CPython [1]의 개발로 인해, 인터프리터를 빌드할 때 사용된 서로 다른 ABI 기능을 구별하는 환경 마커의 필요성이 부각되었습니다. 예를 들어, 현재는 환경 마커로 GIL이 활성화된 CPython 인터프리터와 자유 스레드 CPython 인터프리터를 구별할 방법이 없습니다. 이는 자유 스레딩의 도입과 점진적 보급에 실제적인 문제를 일으킵니다. Python 패키지를 자유 스레드 CPython과 호환되도록 만들 때는 그 패키지의 모든 빌드 및 런타임 의존성도 호환되어야 합니다. 호환되는 의존성의 첫 번째 버전을 메타데이터에 정확하게 기록하는 것은 현재 불가능하며, GIL이 활성화된 빌드에 대해서도 의존성의 최소 버전을 올리는 것은 패키지 간 호환성을 불필요하게 제한하므로 일반적으로 바람직하지 않습니다.

이러한 문제의 몇 가지 구체적인 예가 Environment marker for free-threading Discourse 스레드에서 논의되었습니다:

  • Cython은 master 브랜치에서만 자유 스레딩을 (실험적으로) 지원하며, 이미 cp313t 휠을 배포하는 많은 프로젝트에서 사용되고 있습니다. 잘못된 Cython 버전을 선택하면 원인을 파악하기 어려운 빌드 실패와 런타임 크래시가 많이 발생합니다. 메타데이터로 이를 표현할 수 있다면 유익할 것입니다(Require Cython Pre-release for Free-Threaded Python 참조).
  • CFFI는 아직 자유 스레딩을 지원하지 않으며, 메인테이너 중 한 명인 Armin Rigo는 cffi를 포크하여 자유 스레딩 지원을 구현하고, 해당 기능이 “합리적으로 충분히 테스트된(테스트로든, 또는 이 경우에는 더 바람직하게 여러 다른 프로젝트에서 실제로 사용되면서든)” 후에야 지원을 추가하는 하나의 큰 PR을 가지고 CFFI 프로젝트로 돌아오는 것이 좋은 생각일 수 있다고 밝혔습니다. cffi에 의존하는 프로젝트는 많습니다. 이 프로젝트들이 자유 스레딩에 대해서만 포크에 의존하기 시작하는 것은 아마 괜찮겠지만, >=3.13 또는 모든 Python 버전에 대해 포크에 의존하는 것은 훨씬 더 큰 요구로 보이며 배포 패키저에게도 더 큰 혼란을 줍니다.

이러한 구체적인 예는 올해 안에 Cython과 CFFI가 호환 릴리스를 내놓으면서 해결될 수 있겠지만, 같은 문제가 스택의 더 상위에서 반복될 것입니다. 자유 스레딩의 보급에는 몇 년이 걸릴 것으로 예상되며, 자유 스레딩을 위한 환경 마커가 있으면 그 보급이 훨씬 쉬워질 것입니다.

아직 환경 마커로 다루어지지 않는 또 하나의 중요한 ABI 기능은 인터프리터의 비트 수입니다. 대부분의 경우 플랫폼마다 사용되는 비트 수가 하나뿐이므로 sys_platform 또는 platform_system 마커로 충분합니다. 하지만 Windows에서는 그렇지 않습니다. x86-64 Windows에서는 32비트와 64비트 Python 인터프리터가 모두 널리 사용됩니다. 이 둘을 구별할 수 없다는 점은 컴파일된 확장을 제공하는 패키지에 문제가 될 수 있습니다. 예를 들어, SciPy는 win32 휠을 제공하지 않습니다(Fortran을 지원하는 적절한 32비트 컴파일러 툴체인이 없어서 제공할 수 없습니다). 이러한 휠이 없다는 점은 특히 SciPy가 선택적 의존성일 뿐인 프로젝트에서 곤란할 수 있습니다. 그런 경우, 휠이 없어서 소스로부터의 설치가 실패하는 일을 피하려면 인터프리터가 Windows의 32비트 인터프리터가 아닌 한 SciPy가 필요하다고 지정할 수 있으면 유용할 것입니다(Require SciPy Unless on 32-bit win32 참조).

근거

이 PEP의 목적은 기존 생태계에 미치는 영향을 최소화하면서 핵심 기능을 도입하는 것입니다. PEP 508에서 제안된 기존 문법은 새 환경 마커를 포함하도록 간단히 확장할 수 있습니다.

자유 스레드 Python에 대한 미래 지향적 관점

자유 스레딩에 관해 승인된 제안인 PEP 703은 자유 스레드 Python의 도입이 점진적이어야 한다고 명시하며, Python 운영 위원회는 the PEP 703 acceptance post에서 이것이 여러 릴리스에 걸친 3단계 과정을 의미한다고 명확히 했습니다. 따라서 이 PEP의 메커니즘은 자유 스레딩이나 비자유 스레딩 중 어느 쪽이 기본값이거나 유일한 선택지인 Python 인터프리터에서도 사용할 수 있어야 합니다.

이 글을 쓰는 시점에서 자유 스레드 Python은 1단계: 실험 단계에 있습니다. 이 단계에서는 패키지 작성자들이 점진적으로 지원을 추가함에 따라 자유 스레드 Python으로의 전환을 돕기 위해 제안된 환경 마커가 절실히 필요합니다.

지원하는 패키지의 수가 늘어나더라도, 특히 2단계인 ‘지원되지만 기본값은 아닌’ 단계에서는 전환을 돕는 환경 마커가 여전히 많이 필요할 것으로 예상합니다.

자유 스레드 Python이 3단계: 기본 단계에 들어서면 환경 마커의 필요성은 줄어들 것이지만, 현시점에서는 GIL이 활성화된 Python이 완전히 단계적으로 폐지될지는 분명하지 않습니다(비표준 빌드 옵션으로 계속 제공될 수도 있습니다). GIL이 활성화된 Python이 계속 유지된다면, 반대로 이를 위한 ABI 기능 감지가 필요해질 수 있습니다.

실제로 세 단계 모두에서 패키지 작성자는 ABI 기능에 따라 의존성의 특정 버전을 선택해야 할 수 있으며, 시간이 지나면서 기본값은 GIL 활성화에서 자유 스레딩으로 바뀝니다.

ABI 기능은 이러한 점을 염두에 두고 설계되었으므로, 변화하는 Python 생태계에서 가까운 미래까지 유용하고 단순하게 쓸 수 있습니다.

다른 PEP와의 관계

이 PEP는 ABI 기능을 위해 집합 의미론을 도입하여 환경 마커를 확장합니다. PEP 751에는 잠금 파일 전용 환경 마커를 위한 비슷한 확장이 포함되어 있습니다. 두 확장은 독립적으로 개발되었지만, 새로운 집합 의미론에서 겹치는 부분은 서로 호환됩니다.

명세

이 문서의 키워드 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL””는 RFC 2119에 설명된 대로 해석해야 합니다.

ABI 기능

ABI 기능은 Python 인터프리터의 고유한 속성이며, 단순하고 이해하기 쉬운 문자열로 표현됩니다. 그러나 모든 기능이 모든 Python 인터프리터나 Python 버전에 똑같이 적용되는 것은 아닙니다. 예를 들어, 자유 스레드 인터프리터와 GIL이 활성화된 인터프리터의 구분은 CPython 3.13 이후에만 의미가 있지만, 인터프리터의 비트 수는 모든 인터프리터에 의미가 있습니다.

모든 인터프리터는 다음 ABI 기능을 명시된 대로 반드시(MUST) 처리해야 합니다. 특정 인터프리터로 제한된 ABI 기능을 다른 인터프리터가 제공해서는 안 됩니다(MUST NOT). 기능은 여러 그룹으로 나뉘며, 각 그룹에는 반드시(MUST) 정확히 하나의 기능만 있어야 합니다. 단, 선택 사항으로 표시된 그룹에는 반드시(MUST) 최대 하나의 기능만 있어야 합니다.

free-threading 또는 gil-enabled (CPython 전용)
Python 인터프리터가 자유 스레드라면 free-threading 기능이 반드시 존재해야 하며(MUST) gil-enabled 기능은 존재해서는 안 됩니다(MUST NOT). 그렇지 않으면 gil-enabled 기능이 반드시(MUST) 있어야 하며 free-threading 기능이 있어서는 안 됩니다(MUST NOT).
debug (CPython 전용, 선택 사항)
이 ABI 기능은 CPython의 --with-pydebug 빌드를 위해 예약되어 있습니다. 인터프리터가 Py_DEBUG 기능을 갖춘 CPython 인터프리터이면 debug 기능이 반드시(MUST) 있어야 합니다. POSIX 시스템에서는 이것이 Python 표현식 "d" in sys.abiflags에 해당합니다.
32-bit 또는 64-bit (선택 사항)
인터프리터의 비트 수, 즉 32비트 빌드인지 64비트 빌드인지를 나타냅니다 [2]. 비트 수를 알 수 없거나 32비트도 64비트도 아니면 이 기능이 있어서는 안 됩니다(MUST NOT).

sys_abi_features 환경 마커

의존성 명세에서 ABI 기능을 사용할 수 있도록 의존성 지정자 형식에 새로운 환경 마커 변수인 sys_abi_features가 추가됩니다.

이를 위해서는 PEP 508에서 제시되고 Dependency specifiers에서 유지 관리되는 문법을 확장하고, 가능한 값을 문서화해야 합니다.

env_var의 정의를 다음과 같이 보강하여 sys_abi_features 마커 변수를 포함하도록 문법을 확장합니다.:

env_var       = ('python_version' | 'python_full_version' |
                 'os_name' | 'sys_platform' | 'platform_release' |
                 'platform_system' | 'platform_version' |
                 'platform_machine' | 'platform_python_implementation' |
                 'implementation_name' | 'implementation_version' |
                 'sys_abi_features' |
                 'extra' # ONLY when defined by a containing layer
                 )

문법과 마찬가지로, Dependency specifiers에 있는 환경 마커 개요 표에도 다음 행을 추가합니다:

Marker Python equivalent Sample values
sys_abi_features no direct equivalent available {'free-threading', '64-bit'}, {'gil-enabled', 'debug', '32-bit'}

이러한 추가 사항을 통해, 의존성 명세에서 in 연산자로 기능의 존재 여부를 검사하거나 not in 연산자로 기능의 부재 여부를 검사하는 방식으로 ABI 기능을 사용할 수 있습니다.

예시

자유 스레드 Python에서 Cython 사전 릴리스 요구하기

자유 스레드 Python 인터프리터에서만 Cython의 사전 릴리스를 요구하려면 다음 의존성 명세를 사용할 수 있습니다.:

cython >3.1.0a1; "free-threading" in sys_abi_features
cython ==3.0.*; "free-threading" not in sys_abi_features

32비트 win32가 아닌 경우 SciPy 요구하기

Windows의 32비트 인터프리터가 아닌 경우에 SciPy를 요구하려면 다음 의존성 명세를 사용할 수 있습니다.:

scipy; platform_system != "Windows" or "32-bit" not in sys_abi_features

디버깅 기능이 있는 자유 스레드 인터프리터에서 NumPy 요구하기

디버깅 기능이 있는 자유 스레드 인터프리터에서만 NumPy를 요구하려면 다음 의존성을 사용할 수 있습니다.:

numpy; "free-threading" in sys_abi_features and "debug" in sys_abi_features

하위 호환성

이는 기존 환경 마커에 대한 순수한 확장이며 기존 환경 마커나 의존성 명세에 영향을 주지 않으므로, 직접적인 하위 호환성 문제는 없습니다.

그러나 이 기능의 도입은 여러 생태계 도구, 특히 pyproject.toml 및 requirements.txt의 데이터 검사를 지원하려는 도구들에 영향을 미칩니다.

감사 및 업데이트 도구

다양한 도구가 requirements.txt 파일로 표현된 Python 의존성 데이터를 이해합니다. (예: Dependabot, Tidelift 등)

이러한 도구는 의존성 데이터를 검사하며, 경우에 따라 도구 지원 업데이트나 완전 자동화된 업데이트를 제공합니다. 처음에는 이러한 도구 중 어느 것도 새 환경 마커를 지원하지 않을 것으로 예상하며, 생태계 전반의 지원이 이루어지기까지 수개월 또는 수년이 걸릴 수도 있습니다.

그 결과, 새 환경 마커를 사용하는 사용자는 사용을 시작하는 시점에 워크플로와 도구 지원의 저하를 겪게 될 것입니다. 이는 의존성 데이터를 어디에 어떻게 인코딩할지에 관한 모든 새로운 표준에 해당합니다.

보안 영향

이 PEP는 프로젝트에서 의존성 정보를 지정하기 위한 새로운 문법을 도입합니다. 그러나 의존성을 처리하거나 해석하기 위해 새로 명세된 메커니즘을 도입하지는 않습니다.

따라서 의존성을 설치하는 데 이미 사용되고 있을 수 있는 도구에 내재된 것 이외의 보안 우려는 없습니다—즉, requirements.txt 파일에 악의적인 의존성을 지정할 수 있는 것과 마찬가지로 여기에도 악의적인 의존성을 지정할 수 있습니다.

교육 방법

환경 마커의 사용법은 잘 정립되어 있으며 주로 Dependency specifiers를 통해 전달됩니다. 새 환경 마커도 같은 문서에서 소개할 수 있습니다. 또한 패키지 작성자와 사용자 모두를 위해 Python free-threading guide에서 자유 스레딩 관련 지침을 제공할 수 있습니다.

참조 구현

환경 마커의 참조 구현은 packaging 라이브러리를 포크한 Environment markers for ABI features에서 확인할 수 있습니다.

데모 패키지도 제공됩니다.

pip은 내부적으로 packaging의 벤더링된 사본을 사용하므로, 벤더링된 packaging을 위에 링크된 참조 구현으로 교체한 패치된 버전의 pip도 제공합니다.

기각된 아이디어

확장 메커니즘

이 주제에 관한 초기 논의(Environment marker for free-threading)에서 환경 마커를 위한 일반적인 확장 메커니즘이라는 아이디어가 제기되었습니다. 앞으로 새로운 환경 마커가 필요해질 때 PEP 절차 전체를 거치지 않아도 된다는 점은 매력적이지만, 두 가지 주요 과제가 있습니다.

첫째, 완전히 동적인 메커니즘은 의존성 명세의 정적 분석에 의존하는 도구에 어려움을 초래합니다.

따라서 동적 메커니즘을 채택하더라도 새로운 환경 마커는 여전히 PEP에 명시해야 할 가능성이 높습니다.

둘째로, 동적 메커니즘을 도입하면 packaging 라이브러리, 즉 패키징 라이브러리에 더 복잡한 구현이 필요해지며, 이는 현재 접근 방식에서 크게 벗어나는 것입니다.

미해결 문제

기타 환경 마커

지금 당장 다른 환경 마커가 필요하다면 이 PEP를 확장하여 해당 마커를 포함할 수 있습니다.

기타 도구

참조 구현은 packaging 라이브러리와 pip을 기반으로 합니다. 이를 통해 여러 빌드 백엔드로 패키지를 빌드하고 설치할 수 있음을 확인했습니다. 참조 구현에 다른 도구를 추가해야 할 수도 있습니다.

각주

감사의 글

abi_features 속성을 제안해 주신 Filipe Laíns와, 이 PEP에서 해당 절의 템플릿이 된 PEP 735의 하위 호환성 절을 작성해 주신 Stephen Rosen에게 감사드립니다.