Wie konvertiere ich zwischen Bytes und Strings in Python 3?

75

Dies ist eine Frage vom Typ Python 101, aber sie hat mich eine Weile verwirrt, als ich versuchte, ein Paket zu verwenden, das meine Zeichenfolgeneingabe in Bytes umzuwandeln schien.

Wie Sie weiter unten sehen werden, habe ich die Antwort für mich selbst gefunden, aber ich fand, dass es sich lohnt, hier aufzunehmen, da ich Zeit brauchte, um herauszufinden, was los war. Es scheint generisch für Python 3 zu sein, daher habe ich mich nicht auf das Originalpaket bezogen, mit dem ich gespielt habe. Es scheint kein Fehler zu sein (nur, dass das jeweilige Paket eine .tostring()Methode hatte, die eindeutig nicht das erzeugte, was ich als Zeichenfolge verstand ...)

Mein Testprogramm sieht folgendermaßen aus:

import mangler                                 # spoof package

stringThing = """
<Doc>
    <Greeting>Hello World</Greeting>
    <Greeting>你好</Greeting>
</Doc>
"""

# print out the input
print('This is the string input:')
print(stringThing)

# now make the string into bytes
bytesThing = mangler.tostring(stringThing)    # pseudo-code again

# now print it out
print('\nThis is the bytes output:')
print(bytesThing)

Die Ausgabe dieses Codes ergibt Folgendes:

This is the string input:

<Doc>
    <Greeting>Hello World</Greeting>
    <Greeting>你好</Greeting>
</Doc>


This is the bytes output:
b'\n<Doc>\n    <Greeting>Hello World</Greeting>\n    <Greeting>\xe4\xbd\xa0\xe5\xa5\xbd</Greeting>\n</Doc>\n'

Es muss also in der Lage sein, zwischen Bytes und Strings zu konvertieren, um zu vermeiden, dass Nicht-ASCII-Zeichen in Gobbledegook umgewandelt werden.

Bommel
quelle
1
Diese Frage enthält mehr Details in der Antwort, aber ich denke, die kürzere Antwort unten ist klarer.
Bobble

Antworten:

111

Der 'Mangler' im obigen Codebeispiel hat das Gleiche getan:

bytesThing = stringThing.encode(encoding='UTF-8')

Es gibt andere Möglichkeiten, dies zu schreiben (insbesondere mit bytes(stringThing, encoding='UTF-8'), aber die obige Syntax macht deutlich, was vor sich geht und was zu tun ist, um die Zeichenfolge wiederherzustellen:

newStringThing = bytesThing.decode(encoding='UTF-8')

Wenn wir dies tun, wird die ursprüngliche Zeichenfolge wiederhergestellt.

Beachten Sie , mit str(bytesThing)nur transkribiert alle die gobbledegook ohne ihn wieder in Unicode zu konvertieren, wenn Sie ausdrücklich darum bitten UTF-8, dh., str(bytesThing, encoding='UTF-8'). Es wird kein Fehler gemeldet, wenn die Codierung nicht angegeben ist.

Bommel
quelle
Wenn man sich die tatsächlichen Methode Implementierungen aussehen werden Sie sehen , dass utf-8die Standard - Kodierung ist, daher können Sie es gegeben weglassen , dass Sie wissen , dass die Codierung in der Tat ist utf-8, das heißt stringThing.encode()und bytesThing.decode()wird gut tun.
ccpizza
@ccpizza Wenn Sie die Codierung in den obigen Beispielen explizit angeben, wird viel klarer, was vor sich geht, und IMHO ist eine gute Praxis. Nicht jeder Unicode ist UTF-8. Es vermeidet auch den stillen Fehler, auf den im letzten Absatz Bezug genommen wird.
Bobble
stimme vollkommen zu; expliziter ist besser als implizit, aber imo ist es gut zu wissen , was ist die implizite. Ob man es benutzt oder nicht, ist eine andere Frage. Nur weil du kannst, heißt das nicht, dass du es solltest :)
ccpizza
In Python 3 ist es sicherer, decode('utf-8', 'backslashreplace')eine Ausnahme zu vermeiden, wenn die Codierung unbekannt ist. Man sollte nicht immer UTF-8 annehmen!
Nagev
15

In Python3 gibt es eine bytes()Methode im selben Format wie encode().

str1 = b'hello world'
str2 = bytes("hello world", encoding="UTF-8")
print(str1 == str2) # Returns True

Ich habe in den Dokumenten nichts darüber gelesen, aber vielleicht habe ich nicht an der richtigen Stelle gesucht. Auf diese Weise können Sie Zeichenfolgen explizit in Byte-Streams umwandeln und diese besser lesbar machen als mit encodeund decode, ohne bvor Anführungszeichen vorab zu setzen .

NuclearPeon
quelle
3

Dies ist eine Frage vom Typ Python 101.

Es ist eine einfache Frage, aber eine, bei der die Antwort nicht so einfach ist.


In Python3 repräsentiert ein "Bytes" -Objekt eine Folge von Bytes, ein "String" -Objekt repräsentiert eine Folge von Unicode-Codepunkten.

Um zwischen "Bytes" in "String" und von "String" zurück in "Bytes" zu konvertieren, verwenden Sie die Funktionen bytes.encode und string.decode. Diese Funktionen verwenden zwei Parameter, eine Codierungs- und eine Fehlerbehandlungsrichtlinie.

Leider gibt es sehr viele Fälle, in denen Bytefolgen zur Darstellung von Text verwendet werden, aber es ist nicht unbedingt genau definiert, welche Codierung verwendet wird. Nehmen wir zum Beispiel Dateinamen auf Unix-ähnlichen Systemen. Für den Kernel handelt es sich um eine Folge von Bytes mit einer Handvoll spezieller Werte. In den meisten modernen Distributionen sind die meisten Dateinamen UTF-8, aber es gibt keine Garantie dafür, dass alle Dateinamen dies tun Sein.

Wenn Sie robuste Software schreiben möchten, müssen Sie diese Parameter sorgfältig überlegen. Sie müssen sorgfältig überlegen, in welcher Codierung sich die Bytes befinden sollen und wie Sie mit dem Fall umgehen, in dem sich herausstellt, dass sie keine gültige Folge von Bytes für die Codierung sind, in der sie sich befinden sollten. Python verwendet standardmäßig UTF-8 und Fehler in einer Byte-Sequenz, die nicht gültig ist UTF-8.

print (bytesThing)

Python verwendet "repr" als Fallback-Konvertierung in einen String. repr versucht, Python-Code zu erstellen, der das Objekt neu erstellt. Im Fall eines Byte-Objekts bedeutet dies unter anderem, dass Bytes außerhalb des druckbaren ASCII-Bereichs entkommen.

Plugwash
quelle
1

VERSUCHE DIES:

StringVariable=ByteVariable.decode('UTF-8','ignore')

TYP TESTEN:

print(type(StringVariable))

Hier wird 'StringVariable' als String dargestellt. 'ByteVariable' steht für Byte. Es ist nicht relevant, Variablen in Frage zu stellen.

Tamjid Ahmed
quelle