[Accepted] PEP 687 - Isolating modules in the standard library
원문 링크: PEP 687 - Isolating modules in the standard library
상태: Accepted 유형: Standards Track 작성일: 04-Apr-2022
요약
이 PEP는 표준 라이브러리의 확장 모듈(Extension Modules)을 다단계 초기화(multi-phase initialization, PEP 489) 방식으로 전환하고, 가능한 모든 상태를 프로세스 전역 변수 대신 모듈 객체에 저장하도록 제안합니다.
배경 및 동기
이 제안의 배경, 동기, 합리성, 영향 및 구현 노트는 정보성 PEP 630에 자세히 설명되어 있으며, 이는 확장 모듈 전반에 걸쳐 적용됩니다. PEP 687은 특히 표준 라이브러리의 확장 모듈에 대한 구체적인 내용을 다룹니다. 이 제안의 상당 부분이 이미 구현되었으며, 이 PEP는 변경 사항을 설명하고, 남은 변경 사항을 제안하며, 새로운 모듈에 대한 모범 사례를 설정하는 것을 목표로 합니다.
명세
PEP 630의 본문은 Python 문서의 HOWTO로 변환되고 해당 PEP는 최종(Final)으로 지정될 예정입니다. 표준 라이브러리의 모든 확장 모듈은 PEP 489에서 도입된 다단계 초기화로 전환됩니다.
모든 표준 라이브러리 확장 모듈은 격리됩니다. 이는 다음과 같은 의미를 가집니다.
- 모듈에 의해 정의된 타입(Type), 함수, 기타 객체는 불변(immutable)이거나 다른 모듈 인스턴스와 공유되지 않습니다.
- 모듈에 특정한 상태는 전역 상태를 나타내지 않는 한 다른 모듈 인스턴스와 공유되지 않습니다.
예를 들어, _csv.field_size_limit
는 모듈별 값을 가져오거나 설정하게 됩니다. 반면, readline.get_history_item
또는 os.getpid
와 같은 함수는 프로세스 전역(모듈 외부에 있으며 Python이 아닌 다른 라이브러리와도 공유될 수 있는) 상태를 계속해서 사용합니다.
힙 타입(Heap Types)으로의 전환
모듈 상태 접근이 필요 없고 다른 전환 이유가 없는 정적 타입(static types)은 정적으로 유지되어야 합니다. 메서드가 모듈 인스턴스에 접근해야 하는 타입은 PEP 630에 따라 힙 타입으로 전환됩니다. 이때 다음 사항이 고려됩니다.
- 이전에 정적 타입이었던 모든 표준 라이브러리 타입은 불변성을 유지해야 합니다. 힙 타입은 불변성을 유지하기 위해
Py_TPFLAGS_IMMUTABLE_TYPE
플래그로 정의되어야 합니다. - 불변 타입에 새 속성을 생성하려고 할 때
TypeError
가 발생하는지 테스트로 확인해야 합니다. tp_new = NULL
인 정적 타입은 공개 생성자가 없지만, 힙 타입은 기본 클래스에서 생성자를 상속받습니다. 이전에 인스턴스화가 불가능했던 타입이 해당 특성을 유지하도록Py_TPFLAGS_DISALLOW_INSTANTIATION
을 사용해야 합니다.- 전환된 힙 타입은 의도치 않게 직렬화(
pickle
가능)될 수 있습니다.pickle.dumps
호출 결과가 전환 전후로 동일한지 테스트하고, 실패하면TypeError
를 발생시키는__reduce__
메서드를 추가해야 합니다.
이러한 문제들은 향후 전환을 돕기 위해 개발자 가이드(Devguide)에 추가될 예정입니다.
진행 과정
다음 과정은 모든 모듈이 전환될 때까지 개발자 가이드에 추가되어야 합니다. 새로운 발견 사항은 그곳이나 일반 HOWTO 문서에 기록되어야 합니다.
1단계: 준비
- 버그 트래커 또는 디스커스(Discourse)에서 논의를 시작합니다. 모듈 관리자 및/또는 코드 소유자를 참여시킵니다. 변경 사항의 이유와 배경을 설명합니다.
- 전역 상태 성능 병목 현상을 식별합니다.
- 개념 증명(Proof-of-Concept) 구현을 생성하고 성능 영향을 측정합니다.
pyperf
는 벤치마킹에 유용한 도구입니다. - 구현 계획을 수립합니다. 타입이 적은 소규모 모듈의 경우 단일 PR로 충분할 수 있습니다. 많은 타입과 외부 라이브러리 콜백이 있을 수 있는 대규모 모듈의 경우 여러 PR이 필요합니다.
2단계: 구현
(복잡한 모듈에 대한 제안된 구현 계획이며, 소규모 모듈의 경우 간소화할 수 있습니다.)
- 가능한 곳에 Argument Clinic을 추가합니다. 이를 통해 정의 클래스를 사용하여 타입 메서드에서 모듈 상태를 쉽게 가져올 수 있습니다.
- 모듈 상태를 준비합니다. 모듈 상태 구조체(
module state struct
)를 설정하고, 인스턴스를 정적 전역 변수로 추가하며, 모듈 상태를 가져오기 위한 헬퍼 스텁(helper stubs)을 생성합니다. - 관련 전역 변수를 모듈 상태 구조체에 추가하고, 전역 상태에 접근하는 코드를 모듈 상태 헬퍼를 사용하도록 수정합니다. 이 단계는 여러 PR로 나눌 수 있습니다.
- 필요한 경우 정적 타입을 힙 타입으로 전환합니다.
- 전역 모듈 상태 구조체를 실제 모듈 상태로 전환합니다.
- 다단계 초기화를 구현합니다.
4단계부터 6단계까지는 가급적 단일 알파 개발 단계에서 완료되어야 합니다.
하위 호환성
표준 라이브러리의 확장 모듈은 이제 여러 번 로드될 수 있습니다. 예를 들어, sys.modules
에서 이러한 모듈을 삭제하고 다시 임포트하면 이전에 로드된 인스턴스와 격리된 새로운 모듈 인스턴스가 생성됩니다. 이는 이전 동작(확장 모듈의 전역 변수가 처음 로드된 모듈에서 얕게 복사되던)을 예상했던 코드에 영향을 미칠 수 있습니다.
보안 영향
알려진 보안 영향은 없습니다.
교육 방법
이 제안의 큰 부분은 숙련된 사용자를 대상으로 하는 HOWTO이며, 이는 문서로 이동될 예정입니다. 초보자에게는 영향을 미치지 않을 것입니다.
참고 구현
대부분의 변경 사항은 현재 다음 이슈들에 대한 커밋으로 메인 브랜치에 있습니다.
- bpo-40077: 정적 타입을 힙 타입으로 전환 (PyType_FromSpec() 사용)
- bpo-46417: 내장 Python을 위해 Py_Finalize()에서 정적 타입 지우기
- bpo-1635741: Py_Finalize()가 종료 시 모든 Python 객체를 지우지 않음
예를 들어, _csv
모듈에서 수행된 변경 사항 및 수정 사항은 다음과 같습니다.
- GH-23224:
_csv
모듈에서 정적 상태 제거 - GH-26008:
csv.Error
서브클래싱 허용 - GH-26074:
_csv
힙 타입에 GC 지원 추가 - GH-26351: Python 3.10 알파 기간 동안 전환된 힙 타입을 불변으로 만들기
⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.
Comments