“TypeError: a bytes-like object is required, not ‘str'” beim Umgang mit Dateiinhalten in Python 3
Lesezeit: 6 Minuten
Masroore
Ich habe vor kurzem auf Python 3.5 migriert. Dieser Code funktionierte in Python 2.7 ordnungsgemäß:
with open(fname, 'rb') as f:
lines = [x.strip() for x in f.readlines()]
for line in lines:
tmp = line.strip().lower()
if 'some-pattern' in tmp: continue
# ... code
Aber in 3.5, auf der if 'some-pattern' in tmp: continue line, erhalte ich eine Fehlermeldung, die besagt:
TypeError: a bytes-like object is required, not 'str'
Ich konnte das Problem mit nicht beheben .decode() auf beiden Seiten der innoch konnte ich es mit beheben
if tmp.find('some-pattern') != -1: continue
Was ist falsch und wie kann ich es beheben?
Warum öffnen Sie die Datei im Binärmodus, behandeln sie aber als Text?
– Martijn Pieters ♦
10. Oktober 2015 um 13:28 Uhr
@MartijnPieters danke, dass du den Dateiöffnungsmodus entdeckt hast! Das Ändern in den Textmodus löste das Problem … der Code funktionierte jedoch viele Jahre lang zuverlässig in Py2k …
Ich stoße auch darauf, wo ich eine Anfrage habe result = requests.get und ich versuche es x = result.content.split("\n"). Ich bin ein wenig verwirrt von der Fehlermeldung, weil sie das zu implizieren scheint result.content ist eine Zeichenfolge und .split() erfordert ein Byte-ähnliches Objekt..?? ( “Ein Byte-ähnliches Objekt ist erforderlich, nicht ‘str”‘)..
– Benutzer4805123
25. Februar 2017 um 18:04 Uhr
Martjin hat recht, du solltest das ändern 'rb' Option zu 'r' um die Datei als String zu behandeln
– ThisGuyCantEven
27. September 2021 um 17:27 Uhr
Sie haben die Datei im Binärmodus geöffnet:
with open(fname, 'rb') as f:
Das bedeutet, dass alle aus der Datei gelesenen Daten als zurückgegeben werden bytes Objekte, nicht str. Sie können dann keine Zeichenfolge in einem Containment-Test verwenden:
if 'some-pattern' in tmp: continue
Sie müssten eine verwenden bytes Objekt, gegen das getestet werden soll tmp stattdessen:
if b'some-pattern' in tmp: continue
oder öffnen Sie die Datei stattdessen als Textdatei, indem Sie die 'rb' Modus mit 'r'.
Wenn Sie einen Blick auf die verschiedenen Dokumente werfen, die ppl verlinkt haben, werden Sie sehen, dass alles in Py2 “funktioniert” hat, weil Standard-Strings Bytes waren, während in Py3 Standard-Strings Unicode sind, was bedeutet, dass jedes Mal, wenn Sie I/O machen, insb. Netzwerken, Byte-Strings sind der Standard, also müssen Sie lernen, s/w Unicode & Bytes-Strings zu verschieben (en/decodieren). Für Dateien haben wir jetzt “r” vs. “rb” (und für “w” & “a”), um die Unterscheidung zu erleichtern.
– wescpy
6. März 2017 um 6:24 Uhr
@wescpy: Python 2 hat 'r' vs 'rb'zu, Umschalten zwischen Binär- und Textdateiverhalten (wie das Übersetzen von Zeilenumbrüchen und auf bestimmten Plattformen, wie die EOF-Markierung behandelt wird). Dass die io Bibliothek (die die Standard-E/A-Funktionalität in Python 3 bereitstellt, aber auch in Python 2 verfügbar ist) jetzt auch decodiert Textdateien standardmäßig ist die eigentliche Änderung.
– Martijn Pieters ♦
6. März 2017 um 7:44 Uhr
@MartijnPieters: Ja, einverstanden. In 2.x habe ich nur die verwendet 'b' Flag, wenn mit Binärdateien unter DOS/Windows gearbeitet werden muss (da Binary der POSIX-Standard ist). Es ist gut, dass es einen doppelten Zweck bei der Verwendung gibt io in 3.x für den Dateizugriff.
@ericOnline auch nicht verwenden .readlines() wenn Sie direkt über das Dateiobjekt iterieren können. Vor allem, wenn Sie nur Informationen aus einer einzigen Zeile benötigen. Warum alles in den Speicher lesen, wenn diese Informationen im ersten gepufferten Block zu finden sind?
– Martijn Pieters ♦
7. Januar 2021 um 22:12 Uhr
Theofilos Papapanagiotou
Sie können Ihre Zeichenfolge mit codieren .encode()
Beispiel:
'Hello World'.encode()
Wie der Fehler beschreibt, müssen Sie, um eine Zeichenfolge in eine Datei zu schreiben, diese zuerst in ein Byte-ähnliches Objekt codieren, und encode() codiert es in eine Byte-Zeichenfolge.
Dieser Kommentar war im Zusammenhang mit der Verwendung sehr nützlich fd.subprocess.Popen(); fd.communicate(...);.
– jma
8. Juni 2021 um 13:26 Uhr
Wenn danach eine Verkettung zu einem String benötigt wird (TypeError: kann nur str (nicht “Bytes”) mit str verketten) : "Hello "+("World".encode()).decode() (Das gleiche mit join() offensichtlich).
– Skippy le Grand Gourou
14. Januar 2022 um 18:50 Uhr
Warum funktioniert es?
– Peter Mortensen
15. März 2022 um 22:58 Uhr
Sie können einen String nicht in eine Datei schreiben, dazu müssen Sie den String in ein Byte-ähnliches Objekt kodieren. Durch Ausführen der encode() Methode einer Zeichenfolge, erhalten wir die codierte Version davon in der Standardcodierung, was normalerweise ist utf-8.
– Theofilos Papapanagiotou
17. März 2022 um 15:04 Uhr
Wie bereits erwähnt, lesen Sie die Datei im Binärmodus und erstellen dann eine Liste von Bytes. In Ihrem Folgenden für loop Sie vergleichen String mit Bytes und hier schlägt der Code fehl.
Das Decodieren der Bytes beim Hinzufügen zur Liste sollte funktionieren. Der geänderte Code sollte wie folgt aussehen:
with open(fname, 'rb') as f:
lines = [x.decode('utf8').strip() for x in f.readlines()]
Der Bytes-Typ wurde in Python 3 eingeführt und deshalb funktionierte Ihr Code in Python 2. In Python 2 gab es keinen Datentyp für Bytes:
>>> s=bytes('hello')
>>> type(s)
<type 'str'>
Python 2 hat tatsächlich einen Typ für Bytes, er heißt nur verwirrend str während der Typ für Textzeichenfolgen aufgerufen wird unicode. In Python 3 haben sie die Bedeutung von geändert str damit es genauso war wie das alte unicode Typ, und die alte umbenannt str Zu bytes. Sie haben auch eine Reihe von Fällen entfernt, in denen automatisch versucht wurde, von einem zum anderen zu konvertieren.
Nachdem Sie dies geändert haben, verschwindet der Fehler, aber Sie können nicht in die Datei schreiben (in meinem Fall). Also habe ich doch keine Antwort?
Quelle: So entfernen Sie ^M
Der Wechsel zu ‘rb’ bringt mir den anderen Fehler: io.UnsupportedOperation: write
Shiv Buyya
Verwenden Sie die Funktion encode() zusammen mit dem fest codierten Zeichenfolgenwert, der in einem einfachen Anführungszeichen angegeben ist.
Beispiel:
file.write(answers[i] + '\n'.encode())
Oder
line.split(' +++$+++ '.encode())
Warum funktioniert es?
– Peter Mortensen
15. März 2022 um 23:01 Uhr
Freddy Mcloughlan
Für dieses kleine Beispiel nur das hinzufügen b Vor 'GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n' mein Problem gelöst:
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('www.py4inf.com', 80))
mysock.send(b'GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n')
while True:
data = mysock.recv(512)
if (len(data) < 1):
break
print (data);
mysock.close()
Was macht das Zeichen ‘b’ vor einem String-Literal?
Warum funktioniert es?
– Peter Mortensen
15. März 2022 um 23:01 Uhr
Matan Hugi
Sie haben die Datei im Binärmodus geöffnet:
Der folgende Code löst einen TypeError aus: ein Byte-ähnliches Objekt ist erforderlich, nicht „str“.
for line in lines:
print(type(line))# <class 'bytes'>
if 'substring' in line:
print('success')
Der folgende Code funktioniert – Sie müssen die Funktion decode() verwenden:
for line in lines:
line = line.decode()
print(type(line))# <class 'str'>
if 'substring' in line:
print('success')
14434800cookie-check“TypeError: a bytes-like object is required, not ‘str'” beim Umgang mit Dateiinhalten in Python 3yes
Warum öffnen Sie die Datei im Binärmodus, behandeln sie aber als Text?
– Martijn Pieters
♦
10. Oktober 2015 um 13:28 Uhr
@MartijnPieters danke, dass du den Dateiöffnungsmodus entdeckt hast! Das Ändern in den Textmodus löste das Problem … der Code funktionierte jedoch viele Jahre lang zuverlässig in Py2k …
– Masroore
10. Oktober 2015 um 13:30 Uhr
@masroore siehe: python.org/dev/peps/pep-0404/#strings-and-bytes
– Robert
10. Oktober 2015 um 13:56 Uhr
Ich stoße auch darauf, wo ich eine Anfrage habe
result = requests.get
und ich versuche esx = result.content.split("\n")
. Ich bin ein wenig verwirrt von der Fehlermeldung, weil sie das zu implizieren scheintresult.content
ist eine Zeichenfolge und.split()
erfordert ein Byte-ähnliches Objekt..?? ( “Ein Byte-ähnliches Objekt ist erforderlich, nicht ‘str”‘)..– Benutzer4805123
25. Februar 2017 um 18:04 Uhr
Martjin hat recht, du solltest das ändern
'rb'
Option zu'r'
um die Datei als String zu behandeln– ThisGuyCantEven
27. September 2021 um 17:27 Uhr