PEP 261 – “와이드” 유니코드 문자 지원
- Author:
- Paul Prescod <paul at prescod.net>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 27-Jun-2001
- Python-Version:
- 2.2
- Post-History:
- 27-Jun-2001
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
Python 2.1의 유니코드 문자는 2**16 - 1까지만 서수 값을 가질 수 있습니다. 이 범위는 유니코드에서 기본 다국어 평면(Basic Multilingual Plane)이라고 알려진 범위에 해당합니다. 이제 유니코드에는 다른 “평면”에 존재하는 문자도 있습니다. 유니코드에서 주소 지정 가능한 가장 큰 문자의 서수 값은 17 * 2**16 - 1 (0x10ffff)입니다. 가독성을 위해 이를 TOPCHAR라고 부르고, 이 범위의 문자를 “와이드 문자”라고 부르겠습니다.
용어집
- 문자
- 단독으로 사용될 경우 Python 유니코드 문자열의 주소 지정 가능한 단위를 의미합니다.
- 코드 포인트
- 코드 포인트는 0과 TOPCHAR 사이의 정수입니다. 유니코드를 정수에서 문자로의 매핑이라고 생각하면 각 정수는 코드 포인트입니다. 그러나 문자에 매핑되지 않는 0과 TOPCHAR 사이의 정수도 코드 포인트입니다. 일부는 언젠가 문자에 사용될 것입니다. 일부는 문자에 절대 사용되지 않을 것이 보장됩니다.
- 코덱
- 물리적 인코딩(예: 디스크에 저장된 데이터 또는 네트워크에서 들어오는 데이터)을 논리적 Python 객체로 변환하기 위한 함수 집합입니다.
- 인코딩
- 추상 문자를 물리적인 비트와 바이트로 표현하는 메커니즘입니다. 인코딩을 사용하면 유니코드 문자를 디스크에 저장하고 다른 유니코드 소프트웨어와 호환되는 방식으로 네트워크를 통해 전송할 수 있습니다.
- 서로게이트 쌍
- 하나의 논리적 문자를 나타내는 두 개의 물리적 문자입니다. 32비트 코드 포인트를 두 개의 16비트 코드 포인트로 표현하기 위한 규칙의 일부입니다.
- 유니코드 문자열
- 코드 포인트의 시퀀스를 “문자열 의미론”(예: 대소문자 변환, 정규 표현식 호환성 등)에 따라 나타내는 Python 타입입니다.
unicode()함수로 생성됩니다.
제안된 해결책
한 가지 해결책은 최대 서수 값을 더 큰 값으로 단순히 늘리는 것입니다. 안타깝게도 이 아이디어를 간단하게 구현하는 유일한 방법은 문자당 4바이트를 사용하는 것입니다. 이렇게 하면 대부분의 유니코드 문자열 크기가 두 배가 됩니다. 모든 사용자에게 이러한 비용을 부과하지 않기 위해 Python 2.2에서는 빌드 시 옵션으로 4바이트 구현을 선택할 수 있도록 합니다. 사용자는 와이드 문자가 필요한지 또는 메모리를 보존하는 것을 선호하는지 선택할 수 있습니다.
4바이트 옵션은 “wide Py_UNICODE”라고 합니다. 2바이트 옵션은 “narrow Py_UNICODE”라고 합니다.
대부분의 동작은 wide 환경과 narrow 환경에서 동일합니다.
- 0 <= i <
2**16(0x10000)인 경우unichr(i)는 항상 길이가 1인 문자열을 반환합니다. 2**16<= i <= TOPCHAR인 경우unichr(i)는 wide Python 빌드에서 길이가 1인 문자열을 반환합니다. narrow 빌드에서는ValueError를 발생시킵니다.이슈
Python은 현재 하나의 Python 문자로 표현할 수 없는\U리터럴을 허용합니다. Python은 이를 “서로게이트 쌍”이라고 하는 두 개의 Python 문자로 생성합니다. 향후 narrow Python 빌드에서는 이를 허용하지 않아야 합니까?찬성:
Python은 이미 큰 유니코드 리터럴 문자 이스케이프 시퀀스에 대해 서로게이트 쌍을 구성합니다. 이는 narrow Python 빌드에서도 “와이드 문자”를 구성하는 간단한 방법으로 기본적으로 설계되었습니다. 또한 유니코드 리터럴 구문이 기본적으로 유니코드 이스케이프 코덱을 호출하는 축약형이라는 점을 고려하면 어느 정도 논리적입니다.반대:
이 방법으로 서로게이트를 쉽게 만들 수 있지만 사용자는 여전히 슬라이싱, 인덱싱, 출력 등에 주의해야 합니다. 따라서 일부 사람들은 유니코드 리터럴이 서로게이트를 지원해서는 안 된다고 제안했습니다.이슈
Python은 유니코드 코드 포인트에 대응하지 않는 문자의 구성을 허용해야 합니까? 할당되지 않은 유니코드 코드 포인트는 언제든 할당될 수 있으므로 당연히 허용해야 합니다. 그러나 TOPCHAR보다 큰 코드 포인트는 유니코드에서 절대 사용되지 않는 것이 보장됩니다. 그래도 이에 대한 접근을 허용해야 합니까?찬성:
Python 사용자가 자신이 무엇을 하는지 알고 있다고 생각한다면, 유니코드 사양을 위반하지 못하도록 막으려 해야 하는 이유가 무엇입니까? 결국 8비트 문자열에 ASCII가 아닌 문자가 포함되는 것을 막고 있지는 않습니다.반대:
코덱 및 기타 유니코드 소비 코드는 유니코드 사양에서 허용되지 않는 이러한 문자를 주의해서 처리해야 합니다.ord()는 항상unichr()의 역함수입니다.- 현재 인터프리터에서 유니코드 문자열 내 문자의 가장 큰 서수를 설명하는 정수 값이 sys 모듈에 있습니다.
sys.maxunicode는 Python의 narrow 빌드에서2**16-1(0xffff)이고, wide 빌드에서는 TOPCHAR입니다.이슈:
TOPCHAR에 접근하기 위한 상수와unichr의 정의역에 대한 실제 상한(둘이 다를 경우)에 접근하기 위한 상수를 별도로 두어야 합니까?'wide'와'narrow'값을 취할 수 있는sys.unicodewidth를 두자는 제안도 있었습니다. - 모든 Python 유니코드 문자는 정확히 하나의 유니코드 코드 포인트를 나타냅니다(즉, Python 유니코드 문자 = 추상 유니코드 문자입니다).
- 코덱은 “와이드 문자”를 지원하도록 업그레이드됩니다(UCS-4에서는 직접 표현되고, UTF-8과 UTF-16에서는 가변 길이 시퀀스로 표현됩니다). 이것이 아직 구현해야 할 주요 부분입니다.
- 유니코드 세계에는 32비트 코드 포인트를 두 개의 16비트 코드 포인트로 인코딩하는 관례가 있습니다. 이를 “서로게이트 쌍”이라고 합니다. Python의 코덱은 이 관례를 채택하며, 좁은 Python 빌드에서는 32비트 코드 포인트를 서로게이트 쌍으로 인코딩합니다.
이슈
코덱이 서로게이트를 생성하지 않고 대신 와이드 문자를 오류로 처리하도록 알리는 방법이 있어야 합니까?찬성:
고정 폭 문자만 사용하고 서로게이트를 걱정할 필요가 없는 코드를 작성하고 싶을 수도 있습니다.반대:
이를 코덱에 전달하는 방법에 대한 명확한 제안이 없습니다. - “서로게이트용으로 예약된” 코드 포인트를 부적절하게 사용하는 문자열을 구성하는 데에는 제한이 없습니다. 이를 “고립된 서로게이트”라고 합니다. 코덱은 파일에서 이러한 문자를 읽지 못하게 해야 하지만, 문자열 리터럴이나
unichr()를 사용하여 구성할 수는 있습니다.
구현
새로운 정의가 추가됩니다.:
#define Py_UNICODE_SIZE 2
UCS2 또는 UCS4가 사용 중인지 확인하려면 파생 매크로 Py_UNICODE_WIDE를 사용해야 하며, UCS-4가 사용 중일 때 정의됩니다.
새로운 configure 옵션이 있습니다.
| –enable-unicode=ucs2 | 좁은 Py_UNICODE를 구성하며, 적합한
경우 wchar_t를 사용합니다. |
| –enable-unicode=ucs4 | 와이드 Py_UNICODE를 구성하며, 적합한
경우 wchar_t를 사용합니다. |
| –enable-unicode | “=ucs2”와 같습니다. |
| –disable-unicode | 유니코드 기능을 완전히 제거합니다. |
또한 언젠가는 --enable-unicode가 플랫폼의 wchar_t폭으로 기본 설정되도록 하자는 제안도 있습니다.
와이드 문자에 대한 요청이 거의 없었고, 그러한 요청 대부분이 자체적으로 Python과 Windows를 구매할 수 있는 전문 프로그래머에게서 나왔으며, Windows 자체도 16비트 문자에 강하게 치우쳐 있다는 점을 고려하면 Windows 빌드는 당분간 좁은 형태가 될 것입니다.
참고
이 PEP는 유니코드를 사용하는 사람들이 디스크에 저장하거나 네트워크를 통해 전송하는 파일에 4바이트 인코딩을 사용해야 한다는 의미가 전혀 아닙니다. 단지 그렇게 할 수 있도록 허용할 뿐입니다. 예를 들어 ASCII는 여전히 유효한 (7비트) 유니코드 인코딩입니다.
프로그래머를 위해 좁은 Python 빌드에서 서로게이트를 처리하는 모듈이 있어야 한다는 제안이 있었습니다. 누군가 이를 구현하려 한다면, 그것은 또 다른 PEP가 될 것입니다. 또한 문자, 단어 및 줄 기반의 다른 종류의 색인을 허용하는 기능과 결합할 수도 있습니다.
거부된 제안
대체로 현 상태
Python 문자는 16비트라고 공식적으로 선언하고, 프로그래머가 서로게이트 쌍을 결합하여 애플리케이션 로직에서 와이드 문자를 구현하도록 요구할 수 있습니다. 이는 상당한 부담입니다. 32비트 문자를 전적으로 Python으로 코딩하여 에뮬레이션하면 매우 비효율적일 가능성이 높기 때문입니다. 게다가 이러한 추상화된 의사 문자열은 정규 표현식 엔진의 입력으로 유효하지 않습니다.
“공간 효율적인 유니코드” 유형
또 다른 해결책 유형은 내부적으로 효율적인 저장 방식을 사용하면서 프로그래머에게 와이드 문자에 대한 추상화를 제공하는 것입니다. 이러한 해결책은 어느 것이든 채택된 해결책보다 훨씬 더 복잡한 구현이 필요합니다. 예를 들어 정규 표현식 엔진에 미칠 영향을 고려해 보십시오. 이론적으로는 Python 코드를 손상하지 않고 향후 이 구현으로 전환할 수 있습니다. 향후 Python은 좁은 Python에서 와이드 Python 의미론을 “에뮬레이션”할 수 있습니다. Guido는 지금 당장 이 구현을 맡을 의향이 없습니다.
두 가지 유형
16비트 타입과 나란히 32비트 유니코드 타입을 도입할 수도 있습니다. 유니코드 타입이 단 하나만 존재한다고 가정하는 코드가 많습니다.
이 PEP는 최소 노력 해법을 나타냅니다. 앞으로 몇 년간 32비트 유니코드 문자가 더 흔해질 것이며, 이는 더 정교한 해법이 필요하다는 확신을 우리에게 줄 수도 있고, 반대로 넓은 유니코드 문자를 단순히 강제하는 것이 적절한 해법이라는 확신을 줄 수도 있습니다. 지금 테이블 위에 놓인 두 선택지는 아무것도 하지 않거나 이것을 하는 것입니다.
참고 자료
유니코드 용어집: http://www.unicode.org/glossary/
Copyright
This document has been placed in the public domain.