Python2 에서 Python3로 변경시 유의해야 할 점

아래의 참고자료 중 Python2 to Python3 Porting Guide 를 보면 자세한 설명과 그 이유를 알 수 있으니 해당 문서를 참고하길 바랍니다.

C를 Python3로 포팅

: C에서 Python3로 포팅하는 절차는 크게 3가지로 구성된다.

  1. Modernization, 개발한 코드들이 Python2의 기능으로 마이그레이션 된다. 이 단계 이후에는 Python2.6 이상을 지원하게 된다.
  2. Porting, Python3도입 후 Python3 뿐만 아니라 Python2에 대한 호환성을 유지하도록 만든다.
  3. Cleanup, Python2에 대한 지원을 제거한다. 이 단계 후에는 Python3.3 이상의 버전만을 지원한다.

PyObject

: 모든 object 타입들은 이 PyObject 타입의 확장이라 할 수 있다. 이는 Python이 object를 다루기 위해 해당 object를 가리키는 포인터를 저장하는 구조라고 보면 된다. 이 PyObject는 원본 object의 reference count, 해당하는 object에 대한 type object에 대한 포인터를 가지고 있다.

Modernization

: PyObject의 멤버에 대한 사용에서 다음의 항목들의 사용에 주의하라.

From To 설명
obj->ob_type Py_YPE(obj)  
obj->ob_refcnt Py_REFCNT(obj)  
obj->ob_size Py_SIZE(obj)  
PyObject_HEAD_INIT(NULL) PyVarObject_HEAD_INIT(NULL, 0) type object의 초기화
PyClass_*, Py_Instance_* PyType_* 앞의 두 클래스는 Python3에서 삭제된 클래스, v2.2에서는 유효
PyCObject_* PyCapsule_* Python3.3에서 삭제된 타입

Porting

: modernize의 결과로 당신은 Python2의 가장 최신 feature를 사용하고 있을 것이다. 이제부터는 Python3를 동시에 지원할 수 있도록 할 것이다.

  1. #include <py3c.h>을 통해 헤더파일을 include하고 헤더 파일의 위치를 컴파일러에 알려줘라
  2. Python3에서의 특별한 점은 Python3에서는 human-readable한 string과 binary data를 나누어 놓았다는 점이다. 따라서 py3c 헤더파일을 이용할 때, native stringPyStr_* (PyStr_FromString, PyStr_Type, PyStr_Check 등)을 사용하고 binary dataPyBytes_* (PyBytes_FromString, PyBytes_Type, PyBytes_Check 등)을 사용해라.
String 종류 Py2 Py3 사용처
PyStr_* PyString_* PyUnicode_* Human-readable 텍스트
PyBytes_* PyString_* PyBytes_* Binary data
PyUnicode_* PyUnicode_* PyUnicode_* Unicode strings
PyString_* PyString_* 사용불가 unported code
  1. String의 길이를 return하기 위해서는 PyStr_AsUTF8AndSize()를 사용해라. Python3에서는 PyUnicode_AsUTF8AndSize()가 사용됨에 유의하라.
  2. Python3에서 string이 2 종류(human-readable, binary data)로 분리되었다면, int와 long은 하나의 타입으로 합쳐졌다. 다시말해, PyInt_*은 제거되고 PyLong_*만이 남았다. 이를 py3c 헤더파일에서는 에일리어싱으로 정의해 놓았다.
  3. Python3에서 PyFloat_FromString 함수는 2번째 인자를 없앴다. 이를 py3c 헤더파일에서는 재정의함으로써 Python2와 동시에 지원하고 있다.
  4. 모듈 초기화시 Python2에서는 void init<module_name> 함수를 사용하였으나, Python3에서는 PyObject *PyInit_<module_name>함수를 사용한다. 이를 동시에 지원하기 위해서는 MODULE_INIT_FUNC 매크로를 사용하라.

Cleanup

: Porting의 결과로 Python2와 Python3를 동시에 지원하고 있는 코드를 얻을 수 있다. 여기서는 C에서 Python2와 관련된 문법을 더이상 사용하지 않도록 하는 것이다.

py3c.h 헤더파일이 포함되어있다면 이를 제거하라.

From To 설명
PyStr_* PyUnicode_* PyStr_으로 시작하는 함수는 더이상 사용되지 않음
PyInt_* PyLong_* 더 이상 사용되지 않음
MODULE_INIT_FUNC(module_name) PyMODINIT_FUNC Py_Init_<module_name>(void)  
Py_TPFLAGS_HAVE_WEAKREFS
Py_TPFLAGS_HAVE_ITER
  단순 제거
return PY3C_RICHCMP Py_RETURN_RICHCOMPARE() 링크 참조
capsulethunk.h   사용중이라면 제거하라
#if !IS_PY3 BLOCK   해당 블럭에 있는 코드 제거

참고자료 

[Ofiicial] Embedding Python Application
Python/C API Reference Manual
Python/C API Unicode Objects and Codecs
Python/C API List Objects
Python2 to Python3 Porting Guide
NLTK install guide
stackoverflow - No module name
stackoverflow - Python.h: No such file or directory

+ Recent posts