PEP 399 – 순수 Python/C 가속 모듈 호환성 요구사항
- Author:
- Brett Cannon <brett at python.org>
- Status:
- Final
- Type:
- Informational
- Created:
- 04-Apr-2011
- Python-Version:
- 3.3
- Post-History:
- 04-Apr-2011, 12-Apr-2011, 17-Jul-2011, 15-Aug-2011, 01-Jan-2013
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
CPython 하에서의 Python 표준 라이브러리에는 순수 Python과 C로(전체적으로든 부분적으로든) 구현된 모듈의 다양한 사례가 포함되어 있습니다. 이 PEP는 이러한 사례에서 C 코드가 합리적으로 가능한 한 완전한 대체물로 동작하도록, 순수 Python 코드에 사용되는 테스트 스위트를 반드시 통과해야 함을 요구합니다(C 및 VM 특정 테스트는 예외입니다). 또한 순수 Python 동등 구현이 없는 새로운 C 기반 모듈은 표준 라이브러리에 추가되기 위해 특별한 허가를 받아야 합니다.
근거
Python은 CPython 가상 머신(VM)을 넘어 성장해왔습니다. IronPython, Jython, PyPy_는 모두 현재 CPython VM의 실행 가능한 대안입니다. Python 프로그래밍 언어를 중심으로 생겨난 VM 생태계는 CPython을 사용할 수 없는 여러 다양한 영역에서 Python이 사용되도록 이끌었습니다. 예를 들어, Jython은 Java 애플리케이션에서 Python을 사용할 수 있게 해줍니다.
CPython 외의 모든 VM이 직면하는 문제는 (어느 정도) C로 구현된 표준 라이브러리의 모듈을 처리하는 것입니다. 다른 VM들은 일반적으로 CPython의 C API전체를 지원하지 않으므로, 모듈을 만드는 데 사용된 코드를 사용할 수 없습니다. 이로 인해 종종 이러한 다른 VM들은 모듈을 순수 Python으로, 또는 VM 자체를 구현하는 데 사용된 프로그래밍 언어로(예: IronPython의 경우 C#으로) 재구현하게 됩니다. CPython, PyPy, Jython, IronPython 사이의 이러한 노력 중복은 매우 유감스러운 일인데, 모듈을 적어도 순수 Python으로 구현하는 것만으로도 이러한 중복 노력을 완화하는 데 도움이 될 것이기 때문입니다.
이 PEP의 목적은 Python 표준 라이브러리에 추가되는 모든 새로운 모듈이 특별한 예외가 부여되지 않는 한 순수 Python 구현을 반드시 가지도록 요구함으로써 이러한 중복 노력을 최소화하는 것입니다. 이는 stdlib의 모듈이 CPython뿐만 아니라 모든 VM에서 사용 가능함을 보장합니다(이 요구사항을 충족하지 않는 기존 모듈은 예외이나, 누군가가 나중에 순수 Python 구현을 추가하는 것을 막을 이유는 없습니다).
(CPython의 경우) 모듈의 일부(또는 전체)를 C로 재구현하는 것은 성능상의 이유로 여전히 허용되지만, 이러한 가속 코드는 시맨틱을 검증하고 발산을 방지하기 위해 동일한 테스트 스위트(VM 또는 C 특정 테스트는 제외)를 통과해야 합니다. 이를 달성하기 위해, 가속 코드가 추가되기 전에 해당 모듈의 테스트 스위트가 순수 Python 구현에 대한 포괄적인 커버리지를 가지고 있어야 합니다.
세부사항
Python 3.3부터, 표준 라이브러리에 추가되는 모든 모듈은 순수 Python 구현을 가지고 있어야 합니다. 이 규칙은 Python 개발 팀이 해당 모듈에 대해 특별 예외를 승인한 경우에만 무시될 수 있습니다. 일반적으로 이 예외는 모듈이 특정 C 기반 라이브러리(예: sqlite3)를 감싸는 경우에만 승인됩니다. 예외를 승인함에 있어, 해당 모듈은 CPython에 전용인 것으로 간주되며 다른 VM들이 지원할 것으로 기대되는 Python 표준 라이브러리의 일부가 아닌 것으로 인정됩니다. C 라이브러리를 위한 API를 제공하기 위해 ctypes를 사용하는 것은 계속해서 지양될 것인데, ctypes에는 특정 오류(예: API 변경)의 발생을 방지하기 위해 C 코드가 일반적으로 의존하는 컴파일러 보증이 없기 때문입니다.
이 PEP에 의해 순수 Python 구현이 의무화되지만, 그렇다고 해서 동반 가속 모듈의 사용이 배제되는 것은 아닙니다. 가속 모듈이 제공되는 경우, 그것이 가속하는 모듈과 동일한 이름에 접두사로 밑줄을 붙여 명명되어야 합니다. 예를 들어, warnings에 대해서는 _warnings입니다. 순수 Python 구현에서 가속 코드에 접근하는 일반적인 패턴은 import *로 그것을 임포트하는 것입니다. 예를 들어, from _warnings import *와 같습니다. 이는 일반적으로 모듈의 끝부분에서 이루어지는데, 이는 특정 Python 객체를 그것들의 가속된 대응물로 덮어쓸 수 있도록 하기 위함입니다. 이러한 종류의 임포트는 필요한 경우 모듈의 끝부분 이전에도 수행될 수 있습니다. 예를 들어, 가속된 베이스 클래스가 제공되고 그 후 Python 코드에 의해 서브클래스화되는 경우입니다. 이 PEP는 순수 Python 동등물이 없는 stdlib 내 기존 모듈이 그러한 모듈을 갖도록 의무화하지 않습니다. 그러나 사람들이 순수 Python 동등물을 제공하고 유지보수하는 데 자발적으로 나선다면(예: PyPy 팀이 csv 모듈의 순수 Python 구현을 자발적으로 제공하고 유지보수하는 경우), 그러한 코드는 받아들여질 것입니다. 그러한 경우 C 버전은 예상되는 시맨틱스 측면에서 참조 구현으로 간주됩니다.
새로운 가속화 코드는 합리적으로 가능한 한 순수 파이썬 구현에 가깝게, 즉시 대체 가능한(drop-in replacement) 형태로 동작해야 합니다. 가속화 코드를 제공하는 VM의 기술적 세부 사항은 필요에 따라 다를 수 있습니다. 예를 들어 C로 구현되었을 때 클래스가 type인 경우가 그렇습니다. 파이썬 코드와 이에 대응하는 C 코드가 가능한 한 유사하게 동작하는지 검증하기 위해, 두 코드베이스는 순수 파이썬 코드에 적용되는 것과 동일한 테스트를 사용하여 테스트되어야 합니다(C 코드나 특정 VM에 국한된 테스트는 이 요구 사항의 대상이 아닙니다). 테스트 스위트는 예상되는 시맨틱스를 검증하기 위해 광범위해야 합니다.
즉시 대체 가능한(drop-in replacement) 형태로 동작한다는 것은 또한 순수 파이썬 코드에 존재하지 않는 공개 API를 가속화 코드에서 제공해서는 안 된다는 것을 의미합니다. 이 요구 사항이 없다면, 사람들은 순수 파이썬 구현을 사용하는 다른 VM에는 제공되지 않는 가속화 코드의 세부 사항에 의도치 않게 의존하게 될 수 있습니다. 시맨틱 동등성 계약이 충족되는지 검증하는 데 도움이 되도록, 모듈은 가속화 코드를 사용한 경우와 사용하지 않은 경우 모두에 대해 가능한 한 철저히 테스트되어야 합니다.
예를 들어, 모듈의 순수 파이썬 버전과 C 가속화 버전을 모두 검증하는 테스트를 작성하려면 다음과 같은 기본 관용구를 따를 수 있습니다.:
from test.support import import_fresh_module
import unittest
c_heapq = import_fresh_module('heapq', fresh=['_heapq'])
py_heapq = import_fresh_module('heapq', blocked=['_heapq'])
class ExampleTest:
def test_example(self):
self.assertTrue(hasattr(self.module, 'heapify'))
class PyExampleTest(ExampleTest, unittest.TestCase):
module = py_heapq
@unittest.skipUnless(c_heapq, 'requires the C _heapq module')
class CExampleTest(ExampleTest, unittest.TestCase):
module = c_heapq
if __name__ == '__main__':
unittest.main()
테스트 모듈은 self.heapq 클래스 속성을 통해 heapq 모듈에 접근하는 테스트 메서드를 가진 베이스 클래스(ExampleTest)와, 이 속성을 파이썬 버전 또는 C 버전의 모듈로 설정하는 두 개의 서브클래스를 정의합니다. 두 서브클래스만 unittest.TestCase를 상속한다는 점에 유의하십시오 – 이는 ExampleTest 클래스가 unittest 테스트 탐색에 의해 TestCase 서브클래스로 감지되는 것을 방지합니다. C 모듈을 사용할 수 없을 때 이러한 테스트를 건너뛰도록 하기 위해, C 코드를 테스트하는 클래스에 skipUnless 데코레이터를 추가할 수 있습니다.
이 테스트가 순수 파이썬 구현에서 heapq.heappop()에 대해 광범위한 커버리지를 제공한다면, 가속화된 C 코드는 CPython 표준 라이브러리에 추가될 수 있습니다. 그렇지 않다면, 가속화된 C 코드가 추가되기 전에 적절한 커버리지가 제공될 때까지 테스트 스위트를 갱신해야 합니다.
호환성에도 도움이 되도록, C 코드는 특정 타입에 의도치 않게 의존하는 것을 방지하기 위해 객체에 대한 추상 API를 사용해야 합니다. 예를 들어, 함수가 시퀀스를 받는다면 C 코드는 PyList_GetItem()과 같은 것 대신 기본적으로 PyObject_GetItem()을 사용해야 합니다. C 코드는 적절한 PyList_CheckExact()가 사용된다면 빠른 경로(fast path)를 가질 수 있지만, 그 외의 경우 API는 특정 타입이 아니라 적절한 인터페이스에 덕 타이핑되는 모든 객체와 동작해야 합니다.
Copyright
This document has been placed in the public domain.