Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 331 – 로케일 독립적 부동소수점/문자열 변환

Author:
Christian R. Reis <kiko at async.com.br>
Status:
Final
Type:
Standards Track
Created:
19-Jul-2003
Python-Version:
2.4
Post-History:
21-Jul-2003, 13-Aug-2003, 18-Jun-2004

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

Python 2.3의 LC_NUMERIC 로케일 범주 지원은 파이썬 영역에서만 구현되어 있습니다. 이로 인해 문자열에서 부동소수점을 구문 분석하고 생성하는 C로 구현된 확장 모듈과 라이브러리를 사용하는 애플리케이션에서 일관되지 않은 동작과 스레드 안전성 문제가 발생합니다. 이 문서에서는 필요한 경우 로케일에 종속되지 않는 대체 함수를 제공하고 사용하여 이러한 불일치를 제거하는 계획을 제안합니다.

소개

Python은 locale 모듈을 통해 일반적인 지역화 서비스를 제공하며, 여기에는 숫자 형식의 표시 및 변환 과정을 지역화하는 기능도 포함됩니다. LC_TIMELC_COLLATE와 같은 로케일 범주를 사용하면 애플리케이션의 어떤 측면을 지역화할지 정확하게 구성할 수 있습니다.

LC_NUMERIC 범주는 부동소수점 및 고정 정밀도 숫자의 소수점 구분 기호와 같은 비화폐성 숫자 정보의 형식을 지정합니다. LC_NUMERIC 범주의 지역화는 현재 파이썬 영역에서만 구현되어 있으며, Python 런타임에서 호출하는 C 라이브러리는 Python의 LC_NUMERIC 설정을 인식하지 못합니다. 이는 Python 파서 및 관련 코드에서 사용하는 특정 저수준 함수의 동작을 변경하지 않기 위한 것입니다 [2].

그러나 이는 C 라이브러리를 래핑하는 확장 모듈에 문제를 일으킵니다. 이러한 확장 모듈을 사용하는 애플리케이션은 부동소수점 값을 일관되지 않게 표시하고 변환하게 됩니다.

PyGTK [3]의 작성자인 James Henstridge는 setlocale() 함수에도 스레드 안전성 문제가 있다고 지적했습니다. 스레드가 GIL 외부에서 C 라이브러리의 setlocale()을 호출하여 Python이 부동소수점을 잘못 구문 분석하고 생성하게 만들 수 있기 때문입니다.

근거

LC_NUMERIC에 대한 Python과 C 라이브러리의 지역화 간 불일치는 C 확장을 사용하는 모든 지역화된 애플리케이션에서 문제가 됩니다. 문제의 정확한 양상은 애플리케이션에 따라 달라지지만, 대부분 부동소수점 값을 구문 분석하거나 형식화할 때 발생할 가능성이 높습니다.

문제 예시

이 PEP를 작성하게 된 최초의 문제는 PyGTK 모듈로 래핑된 GTK+ UI 툴킷의 GtkSpinButton [4] 위젯과 관련이 있습니다. 이 위젯은 숫자 모드로 설정할 수 있으며, 이 경우 위젯에 입력된 문자가 숫자로 평가됩니다.

LC_NUMERIC이 C 로케일의 표준과 다른 부동소수점 구분 기호를 사용하는 로케일로 설정되면 문제가 발생합니다(예를 들어 브라질 로케일 pt_BR에서는 ‘.’ 대신 ‘,’를 사용합니다). libc 수준에서 LC_NUMERIC이 설정되지 않기 때문에 스핀버튼의 텍스트 입력란에 부동소수점 값이 잘못 표시되며(구분 기호로 ‘.’를 사용함), ‘,’ 구분 기호를 사용하여 소수 값을 입력할 수 없습니다.

이 간단한 예시는 Python으로 코딩한 이 툴킷 기반 지역화 애플리케이션의 사용성이 저하됨을 보여줍니다.

제안

Martin v. Löwis는 python-dev에서 이 문제에 대한 수용 가능한 해결책의 초기 제약 조건에 대해 다음과 같이 언급했습니다.

  • 파서를 손상시키지 않고 C 라이브러리 수준에서 LC_NUMERIC을 설정할 수 있어야 합니다.
  • float()str()은 로케일을 인식하지 않는 상태로 유지해야 합니다.
  • 로케일을 인식하는 str()atof()은 locale 모듈에 유지해야 합니다.

Python 소스 분석에 따르면 다음 함수는 현재 LC_NUMERIC이 C 로케일로 설정되어 있는지에 의존합니다.

  • Python/compile.c:parsenumber()
  • Python/marshal.c:r_object()
  • Objects/complexobject.c:complex_to_buf()
  • Objects/complexobject.c:complex_subtype_from_string()
  • Objects/floatobject.c:PyFloat_FromString()
  • Objects/floatobject.c:format_float()
  • Objects/stringobject.c:formatfloat()
  • Modules/stropmodule.c:strop_atof()
  • Modules/cPickle.c:load_float()

제안된 접근 방식은 사용자 지정 로캘에 따라 형식이 달라지지 않아야 하는 경우에 이러한 함수를 사용하여, 부동 소수점 형식에서 변환하는(strtod()/atof()) 함수와 변환하는(snprintf()) 함수 중 LC_NUMERIC에 의존하지 않는 함수를 구현하는 것입니다.

locale 모듈도 LC_NUMERIC에 대한 특수 처리를 제거하도록 변경해야 합니다.

이 변경으로 앞서 언급한 스레드 안전성 문제도 해결될 것입니다.

잠재적인 코드 기여

이 문제는 처음에 GTK+ 라이브러리의 문제로 보고되었지만 [5]; 그 이후 Python 구현의 불일치로 정확히 진단되었습니다. 그러나 다행스러운 우연으로, glib 라이브러리(GTK+용으로 주로 개발되었으며 GNU C 라이브러리와 혼동해서는 안 됩니다)는 이 문서에서 제시한 이유와 유사한 이유로 LC_NUMERIC에 의존하지 않는 여러 함수를 구현하고 있습니다(예를 들어 [6] 참조).

동일한 GTK+ 문제 보고서에서 Havoc Pennington은 glib 작성자들이 이 코드를 PSF에 기여할 의향이 있을 것이라고 제안했으며, 이는 이 PEP의 구현을 상당히 단순화할 것입니다. glib 코드의 원저자인 Alex Larsson은 코드를 안전하게 통합할 수 있도록 2003-08-20에 PSF 기여자 협약 [7]을 제출했으며 [8]; 이 협약은 접수되어 승인되었습니다.

위험 요소

제공된 로캘 비의존 함수에는 플랫폼 간 문제가 있을 수 있지만, 제공된 코드가 부동 소수점 수에 적용된 로캘 의존적 변경을 단순히 되돌리므로 이 위험은 낮습니다.

Martin과 Guido는 기여된 코드에 잠재적인 저작권 문제가 있음을 지적했습니다. GTK+ 및 glib 팀의 구성원들이 코드의 라이선스를 변경하는 데 문제가 없다고 밝혔고, 이러한 안전성을 보장하기 위해 PSF 기여자 협약도 우편으로 제출되었으므로 이 영역에서는 문제가 없을 것으로 생각합니다.

Tim Peters는 [9]에서 제안된 변경만으로는 문제를 완전히 해결하기에 충분하지 않은 스레딩 관련 상황이 있다고 지적했습니다. 그러나 현재 완전한 해결책은 존재하지 않습니다.

구현

Gustavo Carneiro <gjc at inescporto.pt>가 구현을 개발하여 Sourceforge.net 버그 774665 [10]에 첨부했습니다.

최종 패치 [11]는 Martin v. Löwis가 버그 보고서에 명시된 대로 2004-06-08에 Python CVS에 통합했습니다.

참고 자료