PEP 223 – \x 이스케이프의 의미 변경
- Author:
- Tim Peters <tim.peters at gmail.com>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 20-Aug-2000
- Python-Version:
- 2.0
- Post-History:
- 23-Aug-2000
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
8비트 문자열과 유니코드 문자열 모두에서 \x 이스케이프가 뒤따르는 정확히 두 개의 16진수 자리를 소비하도록 변경합니다. 이 제안은 이를 원래 설계상의 결함을 바로잡는 것으로 보며, 모든 종류의 문자열에서 더 명확한 표현으로 이어지고, 더 깔끔한 유니코드 처리 방식과 Perl 정규 표현식과의 더 나은 호환성을 제공하며, 기존 코드에 대한 위험을 최소화합니다.
구문
비원시(raw) 문자열의 모든 종류에서 \x 이스케이프의 구문은 다음과 같이 바뀝니다
\xhh
여기서 h는 16진수 자리(0-9, a-f, A-F)입니다. 1.5.2에서의 정확한 구문은 참조 매뉴얼에 명확히 명시되어 있지 않으며, 다음과 같이 되어 있습니다
\xhh...
이는 “두 개 이상”의 16진수 자리를 암시하지만, 한 자리 형식도 1.5.2 컴파일러에서 허용되며, 단순한 \x는 그 자체로(즉, 백슬래시 뒤에 문자 x가 오는 형태로) “확장”됩니다. 참조 매뉴얼이 한 자리 또는 0자리 동작 중 어느 쪽을 의도했는지는 불분명합니다.
의미론
8비트 비원시(raw) 문자열에서
\xij
다음 문자로 확장됩니다
chr(int(ij, 16))
이는 1.6 및 그 이전 버전과 동일하다는 점에 유의하십시오.
유니코드 문자열에서는
\xij
다음과 동일하게 동작합니다
\u00ij
즉, 유니코드 공간의 초기 부분에 있는 명백한 Latin-1 문자로 확장됩니다.
최소 두 개의 16진수 자릿수가 뒤따르지 않는 \x는 컴파일 타임 오류이며, 구체적으로는 8비트 문자열에서는 ValueError이고, 유니코드 문자열에서는 (ValueError의 서브클래스인) UnicodeError입니다. \x뒤에 두 개보다 많은 16진수 자릿수가 오는 경우, 처음 두 개만 “소비”된다는 점에 유의하십시오. 1.6 및 그 이전 버전에서는 마지막 두 개를 제외한 나머지는 조용히 무시되었습니다.
예제
1.5.2에서:
>>> "\x123465" # same as "\x65"
'e'
>>> "\x65"
'e'
>>> "\x1"
'\001'
>>> "\x\x"
'\\x\\x'
>>>
2.0에서:
>>> "\x123465" # \x12 -> \022, "3456" left alone
'\0223456'
>>> "\x65"
'e'
>>> "\x1"
[ValueError is raised]
>>> "\x\x"
[ValueError is raised]
>>>
역사와 근거
\x 이스케이프는 가변 폭 문자 인코딩을 지정하는 방법으로 C에 도입되었습니다. 정확히 어떤 인코딩이었는지, 그리고 몇 개의 16진수 자릿수가 필요한지는 각 구현체에 맡겨졌습니다. 이 언어는 단순히 \x가 뒤따르는 모든 16진수 자릿수를 “소비”한다고 명시했을 뿐, 그 의미는 각 구현체에 맡겼습니다. 따라서 사실상 C에서 \x는 플랫폼별 동작을 제공하기 위한 표준 훅입니다.
파이썬은 명시적으로 플랫폼 독립성을 목표로 하기 때문에, 파이썬의 \x 이스케이프(1.6 버전까지 포함)는 모든 플랫폼에서 동일한 방식으로 처리되었습니다. 즉, 마지막 두 개를 제외한 나머지 16진수 자릿수는 조용히 무시되었습니다. 따라서 파이썬에서 \x 이스케이프의 유일한 실제 용도는 16진수 표기법으로 단일 바이트를 지정하는 것이었습니다.
Larry Wall은 플랫폼 독립적인 언어에서 이것이 \x 이스케이프의 유일한 실제 용도임을 깨달은 것으로 보입니다. 파이썬 2.0을 위해 제안된 규칙이 실제로 Perl이 처음부터 해오던 방식이기 때문입니다(다만 뒤따르는 16진수 자릿수가 2개 미만인 \x 이스케이프에 대해 경고를 받으려면 Perl -w 모드로 실행해야 합니다 – 항상 2개를 고집하는 것이 확실히 더 파이썬다운 방식입니다).
Unicode 문자열이 Python에 도입되었을 때, \x는 일반화되어 Unicode 문자열에서 마지막 네 개의 16진수 자릿수를 제외한 나머지는 무시하게 되었습니다. 이는 새로운 정규 표현식 엔진에 기술적인 어려움을 초래했습니다: SRE는 8비트와 Unicode 패턴 및 문자열을 직관적인 방식으로 혼용할 수 있도록 매우 애를 쓰는데, 예를 들어 r"\x123456"이 패턴으로서 무엇을 의미해야 하는지 더 이상 추측할 방법이 없어졌습니다: 8비트 문자 \x56을 매치하려는 것인지, Unicode 문자 \u3456을 매치하려는 것인지 알 수 없습니다.
억지로 추측하는 방법이 있긴 하지만, 문제는 거기서 끝나지 않습니다. ISO C99 표준은 또한 ISO 10646 문자 공간 전체를 다루기 위해 8자리 \U12345678 이스케이프를 도입하며, Python 2도 처음부터 이를 지원하는 것이 바람직합니다. 그렇다면 \x 이스케이프는 무엇을 의미해야 할까요? 그러면 마지막 여덟 개의 16진수 자릿수를 제외한 나머지는 무시하는 것일까요? Unicode 문자열에서 뒤따르는 자릿수가 8개 미만이면 마지막 4개를 제외한 나머지는 무시할까요? 그리고 4개 미만이면 마지막 2개를 제외한 나머지는 무시할까요?
상황은 시시각각 더 복잡해지고 있었고, 이 제안은 \x를 더 복잡하게 만드는 대신 더 단순하게 만듦으로써 고르디우스의 매듭을 잘라냈습니다. Unicode 문자열에서 \xijkl로의 4자리 일반화 역시 중복이었다는 점에 유의하십시오. 이는 Unicode 문자열에서 \uijkl과 정확히 같은 의미를 가졌기 때문입니다. 16진 표기법을 통해 Unicode 문자를 지정하는 명백한 방법이 단 하나만 있는 것이 더 Python다운 방식입니다.
개발 및 논의
이 제안은 Guido van Rossum, Fredrik Lundh, Tim Peters가 이메일을 통해 함께 다듬었습니다. 이후 2000-08-03부터 Python-Dev에서 “Go x yourself” [1]라는 제목으로 설명되고 논의되었습니다. 반응은 압도적으로 긍정적이었으며, 반대 의견은 제기되지 않았습니다.
하위 호환성
\x 이스케이프의 의미를 바꾸는 것은 기존 코드를 깨뜨릴 위험을 수반하지만, 아직까지는 호환성 문제 사례가 발견되지 않았습니다. 그 위험은 미미할 것으로 여겨집니다.
Tim Peters는 표준 테스트 스위트 중 의도적으로 극단적인 경우를 유발하는 부분을 제외하면, Python CVS 개발 트리나 그의 컴퓨터에 있는 다양한 Python 패키지들 어디에서도 뒤에 16진수가 2개보다 적거나 많은 \xabcdef... 형태의 사례가 없음을 확인했습니다.
참조 매뉴얼이 그런 표기가 합법적이지 않다고 암시했기 때문에(물론 이는 논쟁의 여지가 있습니다!), 2개보다 적은 경우가 있을 가능성은 낮습니다. 2개보다 많은 경우가 있다면, Guido는 그것들이 어차피 버그였다고 주장할 준비가 되어 있습니다 <0.9 wink>.
Guido는 O’Reilly의 Python 책들이 이미 Python이 제안된 방식으로 동작한다고 문서화하고 있다고 보고했는데, 이는 아마도 그 책들의 Perl 편집 전통에서 비롯된 것으로 보입니다(위에서 언급했듯이, Perl은 시작부터 제안된 방식과 (매우 근접하게) 동작했습니다).
Finn Bock은 JPython이 \x 이스케이프를 어떻게 처리하는지가 현재로서는 예측 불가능하다고 보고했습니다. 이 제안은 모든 Python 구현체에서 일관되고 쉽게 구현할 수 있는 명확한 의미를 제공합니다.
다른 도구에 미치는 영향
영향이 없을 것으로 여겨집니다. 문제가 생길 가능성이 있는 후보는 대부분 파싱 도구들이지만, 저자는 “백슬래시가 나오면 다음 문자를 그냥 삼킨다”는 근사치를 넘어서 Python 문자열의 내부 구조를 신경 쓰는 도구를 알지 못합니다. Tim Peters는 python-mode.el, 표준 tokenize.py와 pyclbr.py, 그리고 IDLE 구문 강조 서브시스템을 확인했으며, 이들 중 어느 것도 수정할 필요가 없다고 판단했습니다. tabnanny.py나 checkappend.py 같은 도구들은 tokenize.py로부터 그 면역성을 물려받습니다.
참조 구현
코드 변경 사항이 매우 단순하여 별도의 패치는 만들어지지 않을 것입니다. Fredrik Lundh가 코드를 작성하고 있으며, 이 분야의 전문가이고, 2.0b1이 릴리스되기 전에 단순히 변경 사항을 커밋할 것입니다.
BDFL 선언
예, ValueError이지 SyntaxError는 아닙니다. “리터럴 해석 문제는 전통적으로 구문 오류가 아니라 ‘런타임’ 예외를 일으킵니다.”
참고 자료
Copyright
This document has been placed in the public domain.