HOWTO · Python

Fix Bytes-Like Object Is Required Not STR Error in Python

In diesem Tutorial wird der Bytes-ähnliche-Objekt-ist-notwendig-nicht-str-Fehler in Python besprochen.

Auf dieser Seite

Der Python-TypeError „a bytes-like object is required, not ‘str’“ bedeutet, dass eine Operation Bytes erwartet, aber Text (str) erhalten hat. Prüfen Sie den Wert an der fehlschlagenden Stelle und passen Sie die Operation an die Daten an: Kodieren Sie Text, wenn eine API Bytes benötigt, oder dekodieren Sie Bytes, wenn Sie den Inhalt als Text verarbeiten müssen.

Den „bytes-like object is required, not ‘str’“-TypeError verstehen

Die Meldung benennt beide Seiten des Typkonflikts. „Bytes-like object is required“ beschreibt den Wert, den die Operation akzeptiert; „not ‘str’“ zeigt, dass der übergebene Wert Text war. Der Fehler tritt häufig bei einer Trennzeichenoperation, beim Schreiben in eine Binärdatei oder beim Senden über einen Socket auf. Suchen Sie den konkreten Aufruf und verfolgen Sie das Argument bis zu der Stelle zurück, an der es gelesen, erstellt oder umgewandelt wurde.

Warum Text und Binärdaten nicht zusammenpassen

In Python 3 ist str Text: eine Folge von Unicode-Zeichen. bytes ist eine unveränderliche Folge von Bytewerten, die häufig für kodierten Text, Dateien und Netzwerkdaten verwendet wird. Es handelt sich um unterschiedliche Typen, die nicht austauschbar sind – auch dann nicht, wenn die Bytes lesbare Zeichen darstellen.

Beim Kodieren wird Text mithilfe einer Zeichenkodierung wie UTF-8 in Bytes umgewandelt. Beim Dekodieren werden Bytes mit der entsprechenden Kodierung als Text interpretiert. Welche Umwandlung passt, hängt von der Bedeutung der Daten und dem erwarteten Typ der empfangenden API ab. Eine Umwandlung ohne Prüfung kann den Typkonflikt verschleiern oder Daten beschädigen. Python 2 verwendete andere Konventionen für Strings; sein Verhalten eignet sich daher nicht als Grundlage für Überlegungen zu Python-3-Code.

Text und Bytes an der Schnittstelle umwandeln

Verwenden Sie encode() für Text, wenn Sie ihn an eine API übergeben, die Bytes benötigt. Verwenden Sie decode() für Bytes, wenn Sie in die Textverarbeitung wechseln, und wählen Sie die Kodierung, mit der diese Bytes erzeugt wurden.

Die Umwandlung erfolgt ausdrücklich im Code: So ist erkennbar, an welcher Stelle Text zu Bytes und später wieder zu Text wird. UTF-8 ist eine gängige Wahl für Text, der in einem portablen Format gespeichert oder übertragen werden soll. Lassen Sie den Wert in seiner ursprünglichen Form, bis klar ist, welchen Typ die nächste Operation akzeptiert. Dadurch lässt sich ein Typkonflikt leichter finden und vermeiden, Binärdaten so zu behandeln, als wären sie Text.

Führen Sie dieses Beispiel aus:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

text = "Hello, World!"
data = text.encode("utf-8")
print(data)
print(data.decode("utf-8"))
b'Hello, World!'
Hello, World!

Das Präfix b in der ersten Ausgabezeile kennzeichnet einen bytes-Wert. str(data) ist nicht die Umkehrung der Kodierung: Der Byteinhalt wird dadurch nicht dekodiert. Stattdessen kann eine Darstellung wie b'Hello, World!' entstehen. Verwenden Sie data.decode("utf-8"), wenn die Bytes UTF-8-kodierten Text enthalten und die nächste Operation str erwartet.

Den Fehler in Datei- und Socket-Code beheben

Eine im Binärmodus geöffnete Datei gibt bytes zurück oder erwartet diesen Typ beim Schreiben; im Textmodus übernimmt Python das Dekodieren beziehungsweise Kodieren. Bei Binärdaten behalten Sie den Wert als Bytes bei und verwenden ein Bytes-Trennzeichen, etwa parts = data.split(b","). Enthält die Datei UTF-8-Text und benötigen Sie Textoperationen, dekodieren Sie den Inhalt zuerst und verwenden dann ein Text-Trennzeichen: parts = data.decode("utf-8").split(","). Wandeln Sie einen gelesenen Bytewert nicht mit str() um, in der Erwartung, dass dadurch der Dateiinhalt dekodiert wird.

Dieselbe Typgrenze gilt für Socket-Methoden, die Bytes verarbeiten. sock.sendall(b"hello") übergibt Bytes direkt. Beginnt die Nachricht als Text, kodieren Sie ihn ausdrücklich, zum Beispiel mit sock.sendall(message.encode("utf-8")). Das Beispiel beschreibt den Typ des Arguments; ein tatsächlicher Socket-Austausch setzt außerdem eine verbundene Socket-Verbindung und ein passendes Protokoll auf der Gegenseite voraus.

Den Wert prüfen, bevor Sie eine Umwandlung wählen

Prüfen Sie an der fehlschlagenden Operation den Wert mit type(value) oder mit isinstance(value, bytes) und isinstance(value, str). Ermitteln Sie anschließend den erwarteten Typ der API, entscheiden Sie, ob der Wert Text oder beliebige Binärdaten darstellt, und wandeln Sie ihn nur einmal an dieser Schnittstelle um. Bei Text wählen Sie die Kodierung, die für die Datei oder das Protokoll verwendet wurde. Bei beliebigen Binärdaten behalten Sie die Bytes bei und passen das Trennzeichen oder die Operation so an, dass sie Bytes akzeptiert. So beheben Sie den Typkonflikt, ohne aus dem gedruckten Erscheinungsbild des Werts auf seinen Typ zu schließen.