PEP 461 – bytes와 bytearray에 % 포매팅 추가
- Author:
- Ethan Furman <ethan at stoneleaf.us>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 13-Jan-2014
- Python-Version:
- 3.5
- Post-History:
- 14-Jan-2014, 15-Jan-2014, 17-Jan-2014, 22-Feb-2014, 25-Mar-2014, 27-Mar-2014
- Resolution:
- Python-Dev message
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 Python 2의 str 타입과 유사한 % 포매팅 연산을 bytes와 bytearray에 추가할 것을 제안합니다 [1] [2].
근거
보간은 보통 문자열 연산으로 여겨지지만, bytes나 bytearrays에 대한 보간이 타당한 경우가 있으며, 이 누락된 기능을 메우는 데 필요한 작업은 코드의 전반적인 가독성을 떨어뜨립니다.
동기
Python 3에서 str과 bytes가 분리되면서, 작지만 중요한 프로그래밍 영역 하나가 약간 더 어려워졌고 훨씬 더 고통스러워졌습니다. 바로 와이어 포맷 프로토콜입니다 [3].
이 프로그래밍 영역은 바이너리 데이터와 ASCII 호환 텍스트 조각(즉, ASCII로 인코딩된 텍스트)이 섞여 있다는 특징이 있습니다. bytes와 bytearray에 제한된 % 보간을 되살리면 새로운 와이어 포맷 코드를 작성할 때와 Python 2 와이어 포맷 코드를 이식할 때 모두 도움이 될 것입니다.
일반적인 사용 사례로는 dbf와 pdf 파일 형식, email 형식, FTP와 HTTP 통신 등 여러 가지가 있습니다.
bytes와 bytearray 포매팅에 대해 제안하는 의미 체계
% 보간
모든 숫자 포매팅 코드(d, i, o, u, x, X, e, E, f, F, g, G, 그리고 이후 Python 3에 추가되는 모든 코드)가 지원되며, 패딩, 정렬 및 기타 관련 수정자(현재 #, 0, -, 공백, +이며, Python 3에 추가되는 것도 포함)를 포함하여 str에서와 동일하게 동작합니다. 허용되는 비숫자 코드는 c, b, a, 그리고 s (b의 동의어)뿐입니다.
숫자 코드의 경우, str과 bytes(또는 bytearray) 보간의 유일한 차이점은 이 코드들의 결과가 유니코드가 아니라 ASCII로 인코딩된 텍스트라는 점입니다. 다시 말해, 모든 숫자 포매팅 코드 %x에 대해:
b"%x" % val
다음과 동등합니다:
("%x" % val).encode("ascii")
예시:
>>> b'%4x' % 10
b' a'
>>> b'%#4x' % 10
' 0xa'
>>> b'%04X' % 10
'000A'
%c는 range(256) 범위의 int나 길이가 1인 bytes 인자로부터 단일 바이트를 삽입하며, str로부터는 삽입하지 않습니다.
예시:
>>> b'%c' % 48
b'0'
>>> b'%c' % b'a'
b'a'
%b는 일련의 바이트를 삽입합니다. 이 바이트들은 다음 두 가지 방법 중 하나로 수집됩니다:
- 입력 타입이
Py_buffer[4]를 지원합니까? 그렇다면 이를 사용하여 필요한 바이트를 수집합니다 - 입력 타입이 그 밖의 것입니까? 해당 타입의
__bytes__메서드 [5]를 사용합니다. 메서드가 없으면TypeError를 발생시킵니다
특히 %b는 숫자도 str도 받지 않습니다. str은 문자열을 바이트로 변환하려면 인코딩이 필요한데 우리는 추측하지 않기로 했으므로 거부되며, 숫자는 다음과 같은 이유로 거부됩니다:
- 무엇을 숫자로 볼지가 모호합니다(float? Decimal? Fraction? 사용자 정의 타입?)
- 숫자를 허용하면 숫자와 숫자의 텍스트 표현(3.14 대 ‘3.14’) 사이에 모호함이 생깁니다
- 와이어 포맷의 특성상, 명시적인 것이 암시적인 것보다 확실히 낫습니다
%s는 오직 2/3 코드 베이스를 더 쉽게 유지 관리하기 위한 목적으로 %b의 동의어로 포함되었습니다. Python 3 전용 코드는 %b를 사용해야 합니다.
예시:
>>> b'%b' % b'abc'
b'abc'
>>> b'%b' % 'some string'.encode('utf8')
b'some string'
>>> b'%b' % 3.14
Traceback (most recent call last):
...
TypeError: b'%b' does not accept 'float'
>>> b'%b' % 'hello world!'
Traceback (most recent call last):
...
TypeError: b'%b' does not accept 'str'
%a는 보간되는 값에 대해 repr(some_obj).encode('ascii', 'backslashreplace')와 동등한 결과를 냅니다. 사용 사례로는 새 프로토콜을 개발하면서 스트림에 표지를 기록하는 경우, 기존 프로토콜로 들어가는 데이터를 디버깅하여 문제가 프로토콜 자체에 있는지 잘못된 데이터에 있는지 확인하는 경우, 직렬화 형식의 대체 수단으로 쓰는 경우, 또는 __bytes__를 정의하는 것은 적절하지 않지만 읽기 쉽고 유용한 정보를 담은 표현이 필요한 모든 상황이 있습니다 [6].
%r은 오로지 2/3 코드 베이스를 더 쉽게 유지 보수할 수 있도록 하려는 목적으로 %a의 동의어로 포함됩니다. Python 3 전용 코드에서는 %a를 사용해야 합니다 [7].
예시:
>>> b'%a' % 3.14
b'3.14'
>>> b'%a' % b'abc'
b"b'abc'"
>>> b'%a' % 'def'
b"'def'"
Python 2와의 호환성
앞서 언급했듯이, %s와 %r은 오로지 Python 2에서의 마이그레이션을 쉽게 하거나 Python 2와 단일 코드 베이스를 유지하는 것을 돕기 위해 포함됩니다. 공개된 곳과 비공개 환경 모두에 현재 Python 2의 str 타입을 bytes 컨테이너로 사용하고, 그에 따라 %s를 바이트 보간자로 사용하는 모듈이 있으므로 이는 중요합니다.
그러나 새로 작성하는 Python 3 전용 코드에서는 %b와 %a를 사용해야 하므로, %s와 %r은 즉시 폐지 예정(deprecated)으로 지정되지만 3.x 시리즈에서 제거되지는 않습니다 [7].
제안된 변형
%b에 전달되는 str 인자에 대해 자동으로 .encode('ascii','strict')를 사용하자는 제안이 있었습니다.
- 이는 간헐적인 실패로 이어질 수 있으므로 기각되었습니다. 연산이 항상 실패하도록 하여 문제 지점을 올바르게 고칠 수 있게 하는 편이 낫습니다.
값이 str일 때 %b가 ASCII로 인코딩된 repr을 반환하도록 하자는 제안이 있었습니다 (b’%b’ % ‘abc’ –> b“‘abc’”).
- 이는 문제 발생 지점에서 멀리 떨어진 곳에서 디버깅하기 어려운 실패로 이어질 수 있으므로 기각되었습니다. 연산이 항상 실패하도록 하여 문제 지점을 쉽게 고칠 수 있게 하는 편이 낫습니다.
원래 이 PEP는 format 스타일 포매팅을 추가하는 것도 제안했지만, format과 그 관련 장치는 모두 엄격하게 텍스트(즉, str) 기반이라는 결론이 내려져 제외되었습니다.
__ascii__, __format_bytes__ 등 다양한 새 특수 메서드가 제안되었습니다. 이러한 메서드는 현재로서는 필요하지 않지만, 실제 사용에서 이 해결책의 결함이 드러나면 나중에 다시 검토할 수 있습니다.
경쟁 PEP인 PEP 460 Add binary interpolation and formatting도 존재합니다.
반대 의견
이 PEP에 제기된 반대 의견은 주로 다음 두 가지 주제의 변형이었습니다.
bytes와bytearray타입은 인코딩에 대한 어떤 가정도 없는 순수한 바이너리 데이터를 위한 것입니다- ASCII 인코딩을 가정하는 %-보간을 제공하면 매력적인 골칫거리가 되어 Python 2의
str/unicode텍스트 모델이 가졌던 문제로 우리를 되돌릴 것입니다
논의 과정에서 확인되었듯이, bytes와 bytearray는 바이너리 데이터와 ASCII 호환 구간이 섞인 데이터에도 사용됩니다. dbf와 pdf 같은 파일 형식, ftp와 email 같은 네트워크 프로토콜 등이 그 예입니다.
bytes와 bytearray에는 이미 ASCII 호환 인코딩을 가정하는 메서드가 여럿 있습니다. upper(), isalpha(), expandtabs()가 그중 몇 가지 예입니다. 매우 제한된 미니 언어를 갖춘 %-보간은 이미 존재하는 메서드들보다 더 골칫거리가 되지는 않을 것입니다.
일부는 10진수만으로도 충분하다고 주장하며 모든 범위의 숫자 포매팅 코드를 허용하는 데 반대했습니다. 그러나 적어도 두 가지 형식(dbf와 pdf)은 10진수가 아닌 숫자를 사용합니다.
각주
Copyright
This document has been placed in the public domain.