PEP 461 – Hinzufügen von %-Formatierung zu bytes und bytearray
- Autor:
- Ethan Furman <ethan at stoneleaf.us>
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 13. Jan 2014
- Python-Version:
- 3.5
- Post-History:
- 14. Jan 2014, 15. Jan 2014, 15. Jan 2014, 22. Feb 2014, 25. Mär 2014, 27. Mär 2014
- Resolution:
- Python-Dev Nachricht
Zusammenfassung
Dieser PEP schlägt das Hinzufügen von %-Formatierungsoperationen ähnlich dem str-Typ von Python 2 zu bytes und bytearray vor [1] [2].
Begründung
Während Interpolation üblicherweise als String-Operation betrachtet wird, gibt es Fälle, in denen Interpolation auf bytes oder bytearrays sinnvoll ist, und die Arbeit, die benötigt wird, um diese fehlende Funktionalität zu kompensieren, beeinträchtigt die allgemeine Lesbarkeit des Codes.
Motivation
Mit Python 3 und der Trennung zwischen str und bytes wurde ein kleiner, aber wichtiger Bereich der Programmierung etwas schwieriger und wesentlich schmerzhafter – Wire-Format-Protokolle [3].
Dieser Bereich der Programmierung zeichnet sich durch eine Mischung aus Binärdaten und ASCII-kompatiblen Textsegmenten (auch ASCII-kodierter Text genannt) aus. Die Rückkehr einer eingeschränkten %-Interpolation für bytes und bytearray wird sowohl beim Schreiben von neuem Wire-Format-Code als auch beim Portieren von Python 2 Wire-Format-Code helfen.
Häufige Anwendungsfälle sind dbf und pdf-Dateiformate, email-Formate und FTP und HTTP-Kommunikation, unter vielen anderen.
Vorgeschlagene Semantik für bytes und bytearray-Formatierung
%-Interpolation
Alle numerischen Formatierungscodes (d, i, o, u, x, X, e, E, f, F, g, G und alle, die später zu Python 3 hinzugefügt werden) werden unterstützt und funktionieren wie bei str, einschließlich der Polsterung, Ausrichtung und anderer verwandter Modifikatoren (derzeit #, 0, -, Leerzeichen und + (plus alle, die zu Python 3 hinzugefügt werden)). Die einzigen erlaubten Nicht-numerischen Codes sind c, b, a und s (was ein Synonym für b ist).
Bei den numerischen Codes besteht der einzige Unterschied zwischen str und bytes (oder bytearray) Interpolation darin, dass die Ergebnisse dieser Codes ASCII-kodierter Text und nicht Unicode sind. Mit anderen Worten, für jeden numerischen Formatierungscode %x
b"%x" % val
ist äquivalent zu
("%x" % val).encode("ascii")
Beispiele
>>> b'%4x' % 10
b' a'
>>> b'%#4x' % 10
' 0xa'
>>> b'%04X' % 10
'000A'
%c fügt ein einzelnes Byte ein, entweder aus einem int im Bereich von 256 oder aus einem bytes-Argument der Länge 1, nicht aus einem str.
Beispiele
>>> b'%c' % 48
b'0'
>>> b'%c' % b'a'
b'a'
%b fügt eine Reihe von Bytes ein. Diese Bytes werden auf eine von zwei Arten gesammelt
- Unterstützt der Eingabetyp
Py_buffer[4]? Verwenden Sie ihn, um die notwendigen Bytes zu sammeln - Ist der Eingabetyp etwas anderes? Verwenden Sie seine
__bytes__-Methode [5]; wenn keine vorhanden ist, lösen Sie eineTypeErroraus
Insbesondere akzeptiert %b weder Zahlen noch str. str wird abgelehnt, da die Konvertierung von Zeichenfolgen in Bytes eine Kodierung erfordert, und wir weigern uns zu raten; Zahlen werden abgelehnt, weil
- was eine Zahl ausmacht, ist unklar (Float? Decimal? Fraction? ein Benutzertyp?)
- die Zulassung von Zahlen würde zu Mehrdeutigkeiten zwischen Zahlen und textuellen Darstellungen von Zahlen führen (3.14 vs. '3.14')
- Angesichts der Natur von Wire-Formaten ist explizit definitiv besser als implizit
%s ist als Synonym für %b enthalten, ausschließlich zu dem Zweck, die Wartung von 2/3 Codebasen zu erleichtern. Nur Python 3-Code sollte %b verwenden.
Beispiele
>>> 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 liefert das Äquivalent von repr(some_obj).encode('ascii', 'backslashreplace') für den interpolierten Wert. Anwendungsfälle sind die Entwicklung eines neuen Protokolls und das Schreiben von Markierungen in den Datenstrom; das Debuggen von Daten, die in ein bestehendes Protokoll eingegeben werden, um zu sehen, ob das Problem das Protokoll selbst oder schlechte Daten sind; ein Fallback für ein Serialisierungsformat; oder jede Situation, in der die Definition von __bytes__ nicht angemessen wäre, aber eine lesbare/informative Darstellung benötigt wird [6].
%r ist als Synonym für %a enthalten, ausschließlich zu dem Zweck, die Wartung von 2/3 Codebasen zu erleichtern. Nur Python 3-Code sollte %a verwenden [7].
Beispiele
>>> b'%a' % 3.14
b'3.14'
>>> b'%a' % b'abc'
b"b'abc'"
>>> b'%a' % 'def'
b"'def'"
Kompatibilität mit Python 2
Wie oben erwähnt, werden %s und %r ausschließlich aufgenommen, um die Migration von und/oder eine einheitliche Codebasis mit Python 2 zu erleichtern. Dies ist wichtig, da es Module sowohl im öffentlichen als auch im internen Gebrauch gibt, die derzeit den Python 2 str-Typ als bytes-Container verwenden und daher %s als Bytes-Interpolator verwenden.
Jedoch sollten %b und %a in neuem, nur für Python 3 bestimmtem Code verwendet werden. Daher werden %s und %r sofort als veraltet markiert, aber nicht aus der 3.x-Serie entfernt [7].
Vorgeschlagene Variationen
Es wurde vorgeschlagen, für str-Argumente zu %b automatisch .encode('ascii','strict') zu verwenden.
- Abgelehnt, da dies zu intermittierenden Fehlern führen würde. Es ist besser, wenn die Operation immer fehlschlägt, damit der Fehlerpunkt korrekt behoben werden kann.
Es wurde vorgeschlagen, dass %b die ASCII-kodierte Darstellung zurückgibt, wenn der Wert ein str ist (b'%b' % 'abc' --> b"'abc'").
- Abgelehnt, da dies zu schwer zu debuggenden Fehlern weit entfernt vom Problemort führen würde. Es ist besser, wenn die Operation immer fehlschlägt, damit der Fehlerpunkt leicht behoben werden kann.
Ursprünglich schlug dieser PEP auch das Hinzufügen von Format-String-Formatierung vor, aber es wurde entschieden, dass Format und seine zugehörigen Mechanismen alle strikt textbasiert (auch str) waren, und es wurde verworfen.
Verschiedene neue spezielle Methoden wurden vorgeschlagen, wie z. B. __ascii__, __format_bytes__ usw.; solche Methoden werden derzeit nicht benötigt, können aber später erneut geprüft werden, wenn die reale Nutzung Mängel an dieser Lösung aufzeigt.
Ein konkurrierender PEP, PEP 460 Binäre Interpolation und Formatierung hinzufügen, existiert ebenfalls.
Einwände
Die gegen diesen PEP erhobenen Einwände waren hauptsächlich Variationen zweier Themen
- die
bytesundbytearrayTypen sind für reine Binärdaten, ohne Annahmen über Kodierungen - die %-Interpolation anzubieten, die eine ASCII-Kodierung annimmt, wird eine attraktive Ablenkung sein und uns zu den Problemen des Python 2
str/unicodeTextmodells zurückführen
Wie während der Diskussion zu sehen war, werden bytes und bytearray auch für gemischte Binärdaten und ASCII-kompatible Segmente verwendet: Dateiformate wie dbf und pdf, Netzwerkprotokolle wie ftp und email usw.
bytes und bytearray haben bereits mehrere Methoden, die eine ASCII-kompatible Kodierung annehmen. upper(), isalpha() und expandtabs(), um nur einige zu nennen. %-Interpolation mit ihrer sehr eingeschränkten Mini-Sprache wird keine größere Ablenkung sein als die bereits vorhandenen Methoden.
Einige haben die Zulassung des vollen Bereichs von numerischen Formatierungscodes abgelehnt mit dem Argument, dass Dezimalzahlen allein ausreichend wären. Jedoch verwenden mindestens zwei Formate (dbf und pdf) nicht-dezimale Zahlen.
Fußnoten
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0461.rst
Zuletzt geändert: 2025-02-01 08:55:40 GMT