PEP 689 – 불안정 C API 계층
- Author:
- Petr Viktorin <encukou at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Requires:
- 523
- Created:
- 22-Apr-2022
- Python-Version:
- 3.12
- Post-History:
- 27-Apr-2022, 25-Aug-2022, 27-Oct-2022
- Resolution:
- Discourse message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
C-API의 일부 함수와 타입은 불안정으로 지정됩니다. 즉, 패치(버그 수정/보안) 릴리스에서는 변경되지 않지만, 마이너 릴리스 사이(예: 3.11과 3.12 사이)에서는 폐지 경고 없이 변경될 수 있습니다.
밑줄로 시작하는 C API는 모두 내부로 지정됩니다. 즉, 아무런 예고 없이 변경되거나 사라질 수 있습니다.
동기 및 근거
불안정 C API 계층
파이썬 C-API는 현재 세 가지 안정성 계층으로 나뉩니다:
- 높은 호환성 기대치를 갖는 제한된 API
- 하위 호환성 정책을 따르며, 변경 전에 폐지 경고가 필요한 공개 API
- 언제든지 변경될 수 있는 내부(비공개) API.
CPython 내부에 접근해야 하는 도구(예: 고급 디버거와 JIT 컴파일러)는 흔히 CPython의 마이너 시리즈 릴리스별로 빌드되며, 사용하는 C-API 내부가 패치 릴리스에서는 변경되지 않는다고 가정합니다. 이러한 도구를 지원하려면 공개 C-API와 비공개 C-API 사이에 마이너 시리즈 릴리스 전체에 걸쳐 안정성을 보장하는 계층이 필요합니다. 그것이 바로 여기서 제안하는 불안정 계층입니다.
PyCode_New() 같은 일부 함수는 불안정하다고 문서화되어 있으며(“[이를] 직접 호출하면 특정 Python 버전에 묶일 수 있습니다”), 실제로도 자주 변경됩니다. 불안정 계층은 문서를 충분히 주의 깊게 읽지 않는 사람에게도 이러한 함수의 상태를 분명히 드러내어, 실수로 사용하기 어렵게 만들어야 합니다.
앞쪽 밑줄은 비공개 API 전용으로 남겨 두기
현재 CPython 개발자들은 API 이름 앞에 붙는 밑줄의 정확한 의미에 대해 합의하지 못하고 있습니다. 밑줄은 두 가지 서로 다른 의미로 사용됩니다:
- 여기서 제안하는 불안정 계층처럼 마이너 릴리스 사이에 변경될 수 있는 API(예: PEP 523에서 도입된 함수).
- 비공개이며 CPython 외부에서는 전혀 사용해서는 안 되는 API(예: 예고 없이 변경될 수 있거나, CPython 외부 코드가 보장할 수 없는 문서화되지 않은 가정에 의존하기 때문).
의미가 불분명한 탓에 밑줄이 제 역할을 충분히 하지 못하고 있습니다. 밑줄이 비공개 API만을 나타낸다면, CPython 개발자들은 밑줄 붙은 함수가 CPython 외부에서 어떻게 문서화되거나 사용되는지 조사하지 않고도 그 함수를 변경하거나, 사용되지 않는 함수를 제거할 수 있습니다.
전용 불안정 계층을 도입하면 앞쪽 밑줄의 의미를 명확히 할 수 있습니다. 앞쪽 밑줄은 비공개 API만을 나타내야 합니다.
불필요하게 코드를 깨뜨리지 않기
이 PEP는 불안정 계층의 API가 특별한 이름 접두사를 가져야 한다고 규정합니다. 이는 함수(매크로 등)의 이름을 바꿔야 한다는 뜻입니다. 이름을 바꾼 후에도 호환되지 않는 변경이 이루어질 때까지(즉, 어차피 호출하는 곳을 수정해야 할 때까지) 이전 이름을 계속 사용할 수 있어야 합니다. 다시 말해, 함수의 계층을 바꾸는 것만으로 사용자의 코드가 깨져서는 안 됩니다.
명세
C API는 안정성 기대 수준에 따라 세 가지 “섹션” (내부, 공개, 제한)으로 나뉩니다. 이제부터 이를 안정성 계층, 줄여서 계층이라고 부르겠습니다.
불안정 계층이 추가됩니다.
이 계층의 API(함수, 타입 등)는 앞에 밑줄 없이 PyUnstable_ 접두사가 붙은 이름을 갖습니다.
이 API들은 Include/unstable/ 같은 하위 디렉터리가 아니라 공개 API에 사용되는 헤더(Include/*.h)에 선언됩니다.
불안정 계층을 다루기 위한 몇 가지 규칙이 도입됩니다:
- 불안정 API는 패치 릴리스 간에 하위 호환되지 않는 변경이 없어야 하지만, 마이너 릴리스(3.x.0의 알파 및 베타 릴리스를 포함한 3.x.0)에서는 변경되거나 제거될 수 있습니다. 이러한 변경은 반드시 문서화되어야 하며 What’s New 문서에 언급되어야 합니다.
- 이러한 API에 대한 하위 호환되지 않는 변경은 해당 API를 사용하는 코드가 새 버전으로 컴파일되려면 반드시 수정되어야 하는 방식으로 이루어져야 합니다(예: 인자를 추가하거나 제거하거나 함수의 이름을 바꿔야 하며, 인자의 의미가 바뀌어서는 안 됩니다).
- 불안정 API는 문서화되고 테스트되어야 합니다.
- API를 공개 계층에서 불안정 계층으로 옮기려면 새로운
PyUnstable_*이름으로 노출해야 합니다.기존 이름은 (예:
Py_DEPRECATED로) 폐지 예정으로 표시해야 하지만, API에 호환되지 않는 변경이 이루어질 때까지는 계속 사용할 수 있어야 합니다. Python의 하위 호환성 정책(PEP 387)에 따라, 이 폐지는 (SC 예외 없이) 최소한 두 릴리스 동안 유지되어야 합니다. 하지만 이 기간은 무기한 지속될 수도 있습니다. 예를 들어, PEP 590의 “잠정적인”_PyObject_Vectorcall이 오늘 추가된다면, 처음부터PyUnstable_Object_Vectorcall이라는 이름을 갖게 될 것이며 이 이름을 제거할 계획은 없을 것입니다.다음과 같은 경우에는 해당 함수가 이미 불안정 계층의 일부였던 것처럼, SC 예외 없이도 호환되지 않는 변경(따라서 폐지 예정인 이름의 제거)이 허용됩니다:
- Python 3.12 이전에 도입되었으며 기본보다 덜 안정적이라고 문서화된 모든 API.
- Python 3.12 이전에 도입되었으며 앞에 밑줄이 붙은 이름을 가진 모든 API.
예시는 이 PEP에 명시된 Initial unstable API를 참조하십시오.
- 내부 API를 불안정 계층으로 옮기려면 새로운
PyUnstable_*이름으로 노출해야 합니다.기존 이름이 문서화되어 있거나 외부에서 널리 사용되고 있다면, 호환되지 않는 변경이 이루어질 때(그리고 호출 지점을 수정해야 할 때)까지 계속 사용할 수 있어야 합니다. 기존 이름은 (예:
Py_DEPRECATED를 사용하여) 폐지 예정 경고를 발생시키기 시작해야 합니다. - API를 불안정 계층에서 공개 계층으로 옮기려면
PyUnstable_*접두사 없이 노출해야 합니다.기존 이름은 해당 API가 폐지 예정이 되거나 제거될 때까지 계속 사용할 수 있어야 합니다.
- 기존 기능을 위한 새로운 불안정 API의 추가는 베타 기능 동결 이후에도 첫 번째 릴리스 후보까지 허용됩니다. 베타 기간에는 Core Development Discourse에서의 합의가 필요합니다.
이 규칙들은 개발자 가이드에 문서화되며, 사용자 문서도 그에 맞게 갱신됩니다.
PyUnstable_* 이름을 가진 C API의 레퍼런스 문서에는 불안정 계층 문서로의 링크가 포함된 안내가 자동으로 표시됩니다.
앞에 붙는 밑줄
앞에 밑줄이 붙은 이름을 가진 C API와 Py_BUILD_CORE에서만 사용할 수 있는 API는 내부로 간주됩니다. 이는 다음을 의미합니다:
- 이러한 API는 마이너 릴리스(3.x.0의 알파 및 베타 릴리스를 포함한 3.x.0)에서 예고 없이 변경되거나 제거될 수 있습니다. 패치 릴리스나 릴리스 후보에서의 API 변경은 반드시 필요한 경우에만 이루어져야 합니다.
- 이러한 API는 공개 문서가 아니라 소스 주석이나 개발자 가이드에만 문서화되어야 합니다.
- Python 3.12 이전에 도입되었으며 문서화되었거나 외부에서 널리 사용되는 API는 위에서 설명한 대로 불안정 계층으로 옮겨야 합니다.
이러한 일은 이 PEP가 수락되고 한참 뒤에 일어날 수도 있습니다. 따라서 몇 년 동안 코어 개발자는 밑줄로 시작하는 API를 변경하기 전에 어느 정도 조사를 해야 합니다. 그 API에
Py_BUILD_CORE가 필요하지 않다면 더욱 그렇습니다.
C API 사용자는 자신의 코드베이스에서 _Py 및 _PY 식별자 접두사를 검색하고, 발견된 항목을 모두 결국 수정해야 할 문제로 취급하는 것이 좋습니다. 기존 대안으로 전환하거나, 해당 사용 사례를 위한 공개 API 노출을 요청하는 CPython 이슈를 열고 결국 그 API로 전환하는 방식으로 수정할 수 있습니다.
초기 불안정 API
개념 증명으로서 다음 API를 초기 구현에서 불안정(Unstable) 계층으로 옮깁니다.
코드 객체 생성자:
PyUnstable_Code_New()(PyCode_New에서 이름 변경)PyUnstable_Code_NewWithPosOnlyArgs()(PyCode_NewWithPosOnlyArgs에서 이름 변경)
코드 추가 정보 (PEP 523):
PyUnstable_Eval_RequestCodeExtraIndex()(_PyEval_RequestCodeExtraIndex에서 이름 변경)PyUnstable_Code_GetExtra()(_PyCode_GetExtra에서 이름 변경)PyUnstable_Code_SetExtra()(_PyCode_SetExtra에서 이름 변경)
Python 3.12에서는 별도의 PEP 없이 더 많은 API가 추가될 것으로 예상됩니다.
하위 호환성
C API의 하위 호환성에 대한 기대 수준이 더 명확해집니다.
이름이 변경된 모든 API는 가능한 한 오랫동안 이전 이름으로도 사용할 수 있습니다.
교육 방법
이 변경 사항은 고급 C 프로그래머에게 영향을 미칩니다. 이들은 갱신된 레퍼런스 문서, 개발자 가이드(devguide), What’s New 문서 중 하나 이상을 참고해야 합니다.
참조 구현
https://github.com/python/cpython/compare/main…encukou:unstable-tier
기각된 아이디어
특별한 접두사 없음
이 PEP의 초기 버전에서는 불안정 API에 PyUnstable 접두사가 없었습니다. 대신, Py_USING_UNSTABLE_API를 정의하면 해당 소스 파일에서 그 API를 사용할 수 있었으며, 이는 각 Python 릴리스마다 파일 전체를 다시 검토해야 할 수도 있다는 점을 인정하는 일종의 감사의 글(acknowledgement) 역할을 했습니다.
그러나 불안정성은 개별 이름에 드러나야 한다고 결정되었습니다.
밑줄 접두사
비공개 API와 불안정 API를 모두 이름 앞에 밑줄을 붙여 표시할 수도 있습니다. 그러나 그렇게 하면 _Py 접두사의 의미가 희석됩니다. 이 접두사를 내부 API 전용으로 남겨 두면 검색하기가 아주 쉬워집니다.
새 헤더 디렉터리
다른 API 계층에는 헤더 전용 디렉터리(Include/cpython/, Include/internal/)가 있습니다.
불안정 계층은 매우 명확한 명명 규칙을 사용하고 그 이름을 항상 사용할 수 있으므로, Include/unstable/ 같은 디렉터리는 필요하지 않습니다.
Python API
Python(C가 아닌) API에도 비슷한 계층을 추가하는 것이 좋을 수 있습니다. 예를 들어 types.CodeType에 대해서입니다. 그러나 그러려면 다른 메커니즘이 필요합니다. 이는 이 PEP의 범위를 벗어납니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.