PEP 687 – 표준 라이브러리에서 모듈 격리하기
- Author:
- Erlend Egeberg Aasland <erlend at python.org>, Petr Viktorin <encukou at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Requires:
- 489, 573, 630
- Created:
- 04-Apr-2022
- Python-Version:
- 3.12
- Post-History:
- 04-Apr-2022, 11-Apr-2022
- Resolution:
- Discourse message
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
표준 라이브러리의 확장 기능은 다중 단계 초기화(PEP 489)로 변환되며, 가능한 경우 모든 상태는 프로세스 전역 변수 대신 모듈 객체에 저장됩니다.
소급 적용에 관한 참고 사항
이 제안의 상당 부분은 이미 구현되었습니다. 변경 사항을 설명하고, 변경 사항이 적절한지에 대한 합의를 구하며, 남은 변경 사항을 제안하고, 새 모듈을 위한 모범 사례를 정립하기 위해 이 PEP를 제출합니다.
동기 및 근거
정보 제공용 PEP 630은 제안된 변경 사항이 표준 라이브러리뿐만 아니라 모든 확장 모듈에 일반적으로 적용될 때의 배경, 동기, 근거, 영향 및 구현 참고 사항을 설명합니다.
이는 이 제안의 필수적인 부분입니다. 먼저 읽으십시오.
이 PEP에서는 표준 라이브러리의 구체적인 사항을 다룹니다.
명세
파이썬 문서에서 PEP 630의 본문은 HOWTO로 변환되며, 해당 PEP는 폐기됩니다(최종으로 표시됩니다).
표준 라이브러리의 모든 확장 모듈은 PEP 489에 도입된 다중 단계 초기화로 변환됩니다.
모든 표준 라이브러리 확장 모듈은 격리됩니다. 즉, 다음과 같습니다.
- 모듈에서 정의하는 타입, 함수 및 기타 객체는 불변이거나 다른 모듈 인스턴스와 공유되지 않습니다.
- 모듈에 특정한 상태는 전역 상태를 나타내는 경우를 제외하고 다른 모듈 인스턴스와 공유되지 않습니다.
예를 들어,
_csv.field_size_limit은 모듈별 숫자를 가져오거나 설정합니다. 반면readline.get_history_item이나os.getpid와 같은 함수는 프로세스 전역 상태(모듈 외부에 있으며 Python이 아닌 라이브러리를 포함한 다른 라이브러리와 공유될 수도 있음)를 계속 사용합니다.
힙 타입으로의 변환
모듈 상태에 접근할 필요가 없고 변환해야 할 다른 이유도 없는 정적 타입은 정적으로 유지해야 합니다.
메서드에서 해당 모듈 인스턴스에 접근해야 하는 타입은 다음 사항을 고려하여 PEP 630에 따라 힙 타입으로 변환됩니다.
- 이전에 정적 타입이었던 모든 표준 라이브러리 타입은 계속 불변으로 유지해야 합니다. 힙 타입은 불변성을 유지하도록
Py_TPFLAGS_IMMUTABLE_TYPE플래그를 사용하여 정의해야 합니다. bpo-43908을 참조하십시오.테스트에서는 불변 타입의 새 속성을 만들려고 할 때
TypeError가 발생하는지 확인해야 합니다. tp_new = NULL인 정적 타입에는 공개 생성자가 없지만, 힙 타입은 기본 클래스에서 생성자를 상속합니다. 이전에 인스턴스화할 수 없었던 타입이 해당 특성을 유지하는지 확인하십시오.Py_TPFLAGS_DISALLOW_INSTANTIATION을 사용하십시오.test.support.check_disallow_instantiation()을 사용하여 테스트를 추가하십시오. bpo-43916을 참조하십시오.- 변환된 힙 타입은 의도치 않게 직렬화 가능해질 수 있습니다 (
pickle-able).pickle.dumps를 호출한 결과가 변환 전후에 동일한지 테스트하고, 테스트에 실패하면TypeError를 발생시키는__reduce__메서드를 추가하십시오. 예시는 PR-21002를 참조하십시오.
향후 변환에 도움이 되도록 이러한 문제를 Devguide에 추가합니다.
다른 종류의 문제가 발견되면 해결책을 찾아 Devguide에 추가할 때까지 해당 모듈을 변경하지 말고, 이미 변환된 모듈을 확인하여 수정해야 합니다.
프로세스
다음 프로세스를 Devguide에 추가하고 모든 모듈이 변환될 때까지 유지해야 합니다. 새롭게 발견되는 사항은 Devguide 또는 일반 HOWTO에 문서화해야 합니다.
1부: 준비
- 버그 추적기나 Discourse에서 토론을 시작하십시오. 모듈 유지 관리자 및/또는 코드 소유자를 참여시키십시오. 변경의 이유와 근거를 설명하십시오.
- 전역 상태의 성능 병목을 식별하십시오. 개념 증명 구현을 만들고 성능 영향을 측정하십시오.
pyperf는 벤치마킹에 좋은 도구입니다. - 구현 계획을 작성하십시오. 타입이 적은 작은 모듈의 경우 단일 PR로 처리할 수 있습니다. 타입이 많고 외부 라이브러리 콜백도 있을 수 있는 대형 모듈의 경우 여러 PR이 필요합니다.
2부: 구현
참고: 이는 다른 모듈에서 얻은 교훈을 바탕으로 한 복잡한 모듈의 권장 구현 계획입니다. 작은 모듈에는 자유롭게 단순화하십시오.
- 가능한 경우 Argument Clinic을 추가하십시오. 그러면 타입을 정의하는 클래스를 사용하여 타입 메서드에서 모듈 상태를 쉽게 가져올 수 있습니다.
- 모듈 상태를 준비하십시오. 모듈 상태
struct를 설정하고, 인스턴스를 정적 전역 변수로 추가하며, 모듈 상태를 가져오는 도우미 스텁을 생성하십시오. - 모듈 상태
struct에 관련 전역 변수를 추가하고, 전역 상태에 액세스하는 코드를 대신 모듈 상태 도우미를 사용하도록 수정하십시오. 이 단계는 여러 PR로 나누어 진행할 수 있습니다. - 필요한 경우 정적 타입을 힙 타입으로 변환하십시오.
- 전역 모듈 상태 구조체를 실제 모듈 상태로 변환하십시오.
- 다단계 초기화를 구현하십시오.
4단계부터 6단계까지는 하나의 알파 개발 단계에서 반영하는 것이 바람직합니다.
하위 호환성
표준 라이브러리의 확장 모듈을 이제 두 번 이상 로드할 수 있게 됩니다. 예를 들어 sys.modules에서 해당 모듈을 삭제하고 다시 가져오면, 이전에 로드된 어떤 인스턴스와도 격리된 새 모듈 인스턴스가 생성됩니다.
이는 이전 동작을 예상한 코드에 영향을 줄 수 있습니다. 확장 모듈의 전역 변수는 처음 로드된 모듈에서 얕게 복사되었습니다.
보안 관련 영향
알려진 사항이 없습니다.
이 내용을 가르치는 방법
이 제안의 상당 부분은 숙련된 사용자를 대상으로 하는 HOWTO이며, 문서로 옮겨질 예정입니다.
초보자에게는 영향이 없어야 합니다.
참조 구현
대부분의 변경 사항은 이제 다음 이슈에 대한 커밋으로 메인 브랜치에 반영되었습니다:
- bpo-40077, 정적 타입을 힙 타입으로 변환: PyType_FromSpec() 사용
- bpo-46417, 임베디드 Python에서 Py_Finalize()의 정적 타입 지우기
- bpo-1635741, 종료 시 Py_Finalize()가 모든 Python 객체를 지우지 않음
예로서, _csv 모듈에서 수행된 변경 및 수정 사항은 다음과 같습니다:
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.