PEP 460 – 바이너리 보간 및 포맷팅 추가
- Author:
- Antoine Pitrou <solipsis at pitrou.net>
- Status:
- Withdrawn
- Type:
- Standards Track
- Created:
- 06-Jan-2014
- Python-Version:
- 3.5
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 bytes 및 bytearray 객체에 최소한의 서식 지정 연산을 추가할 것을 제안합니다. 제안된 추가 사항은 다음과 같습니다.
- 퍼센트 포맷팅을 위한
bytes % ...및bytearray % ...로,str객체의 퍼센트 포맷팅과 구문이 유사합니다(단일 객체, 튜플 또는 딕셔너리를 허용합니다). bytes.format(...)및bytearray.format(...)으로,str.format()과 구문이 유사한 포맷팅을 제공합니다(위치 인자와 키워드 인자를 모두 허용합니다).bytes.format_map(...)및bytearray.format_map(...)으로,str.format_map(...)과 유사한 API를 제공하며,bytes.format()및bytearray.format()과 동일한 포맷팅 구문과 의미론을 사용합니다.
근거
Python 2에서는 str % args 및 str.format(args)를 사용하여 바이트 문자열을 포맷팅하고 보간할 수 있습니다. 이 기능은 프로토콜이 고정 인코딩을 사용하는 것으로 알려진 경우 프로토콜 메시지를 조립하는 데 흔히 사용되었습니다.
Python 3에서는 일반적으로 텍스트를 유니코드로 저장하고 조작해야 합니다(즉, bytes가 아닌 str 객체로 처리해야 합니다). 그러나 일부 경우에는 bytes 객체를 직접 조작하는 것이 타당합니다. 일반적인 사용 사례는 바이너리 네트워크 프로토콜로, 여러 바이트 객체(일부는 리터럴이고 일부는 계산된 값)를 보간하고 조합하여 완전한 프로토콜 메시지를 생성할 수 있습니다. 예를 들어 HTTP나 SIP와 같은 프로토콜에는 ASCII 이름과, 인코딩이 다양하거나 때로는 명확하게 정의되지 않은 불투명한 “텍스트” 값으로 이루어진 헤더가 있습니다. 게다가 이러한 헤더 뒤에는 바이너리 본문이 올 수 있으며… 이 본문은 청크로 나뉘고 ASCII 헤더와 트레일러로 장식될 수 있습니다!
bytearray 객체, bytes.join 메서드 또는 심지어 io.BytesIO를 사용하는 등 바이너리 데이터를 누적하는 상당히 효율적인 방법들이 있지만, 그 어느 것도 %-포맷팅 또는 {}-포맷팅 템플릿과 포맷팅 연산으로 만들어지는 것과 같은 읽기 쉽고 직관적인 코드를 제공하지는 않습니다.
바이너리 포맷팅 기능
지원되는 기능
이 제안에서 bytes 및 bytearray의 퍼센트 포맷팅은 다음 기능을 지원합니다.
- 위치뿐만 아니라 이름으로도 포맷팅 인자를 조회합니다(즉,
%s와%(name)s를 모두 지원합니다). %s는 주어진 값에서Py_buffer를 가져오려고 시도하고, 실패하면__bytes__를 호출합니다. 그 결과로 생성된 바이너리 데이터는 문자열의 지정된 위치에 삽입됩니다. 이는 bytes, bytearray 및 memoryview 객체뿐만 아니라 pathlib의 경로 객체와 같은 몇 가지 다른 객체에서도 작동할 것으로 예상됩니다.%c는 0에서 255 사이의 정수를 허용하고, 주어진 값의 바이트를 삽입합니다.
bytes 및 bytearray의 중괄호 포맷팅은 다음 기능을 지원합니다.
str.format()에서 지원하는 모든 종류의 인자 조회(명시적 위치 조회, 자동 증가 위치 조회, 키워드 조회, 속성 조회 등)를 지원합니다.- 수정자나 레이아웃이 지정되지 않은 경우 바이너리 데이터를 삽입합니다(예:
{},{0},{name}). 이는 퍼센트 포맷팅에서%s가 사용하는 것과 동일한 의미론을 가집니다(위 참조). c수정자는 0에서 255 사이의 정수를 허용하고, 주어진 값의 바이트를 삽입합니다(위의%c와 동일합니다).
지원되지 않는 기능
str 객체의 포맷팅에 존재하는 다른 모든 기능(퍼센트 연산자 또는 str.format() 메서드를 통한 기능)은 지원되지 않습니다. 그러한 기능은 연산자나 메서드가 적용되는 대상을 텍스트로 취급한다는 의미이며, 이는 텍스트와 바이트의 분리 원칙에 어긋납니다(예를 들어, %d를 서식 코드로 허용하면 bytes 객체가 실제로 ASCII 호환 텍스트 문자열이라는 의미가 됩니다).
지원되지 않는 기능에는 대부분의 형식별 형식 코드뿐만 아니라 패딩이나 정렬과 같은 다양한 레이아웃 지정자도 포함됩니다. 또한 str 객체는 예를 들어 %s 형식 코드를 사용하는 경우에도 형식 지정 연산의 인자로 허용되지 않습니다.
__format__은 호출되지 않습니다.
비판
- 개발 비용과 유지 관리 비용입니다.
- 3.3에서는 ASCII 또는 latin-1로 인코딩하는 작업이 memcpy만큼 빠르지만, 여전히 별도의 객체를 생성합니다.
- 개발자가 Python 3.4 및 이전 버전을 지원하려면 어쨌든 바이너리 형식 지정 기능의 부재를 우회해야 합니다.
- bytes.join()은 바이트 문자열을 결합할 때 format보다 일관되게 빠릅니다(XXX 정말 그렇습니까?).
- 형식 지정 함수는 내장 형식에 추가하는 대신 서드파티 모듈에서 구현할 수 있습니다.
기타 제안
새로운 형식 데이터 형식
“네트워크 프로그래밍”에 특화된 새로운 데이터 형식을 만들자는 제안이 있었습니다. 이 PEP의 작성자들은 이것이 역효과를 낳는다고 생각합니다. Python 3에는 이미 바이너리 데이터 조작을 전담하는 몇 가지 주요 형식이 있습니다: bytes, bytearray, memoryview, io.BytesIO.
또 다른 형식을 추가하면 사용자에게 더욱 혼란을 주고, 라이브러리 간 상호 운용성이 더 어려워집니다(필요한 변환으로 인해 잠재적으로 최적이 아닌 결과가 발생할 수도 있습니다).
또한 하나의 형식만 필요한 것이 아니라 두 가지 형식이 필요합니다. 하나는 해싱을 허용하기 위한 불변 형식이고, 다른 하나는 네트워크 메시지 작업에서 효율적인 누적이 필요한 경우가 많기 때문에 가변 형식입니다.
해결
이 PEP는 모듈로 연산자와 함께 바이트 객체에 더욱 확장된 형식 지정 언어를 도입하는 PEP 461의 acceptance로 인해 더 이상 유효하지 않습니다.
참고 자료
Copyright
This document has been placed in the public domain.