“TypeError: a bytes-like object is required, not ‘str'” beim Umgang mit Dateiinhalten in Python 3

Lesezeit: 6 Minuten

Benutzeravatar von masroore
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 …

    – 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 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.

    – wescpy

    7. März 2017 um 2:14 Uhr

  • @ericOnline ZipFile.open() Dokumente ausdrücklich angeben, dass nur der Binärmodus unterstützt wird (Zugriff auf ein Mitglied des Archivs als binär dateiähnliches Objekt). Sie können das Dateiobjekt einschließen io.TextIOWrapper() um den gleichen Effekt zu erzielen.

    – Martijn Pieters

    7. Januar 2021 um 22:01 Uhr


  • @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

Benutzeravatar von Theofilos Papapanagiotou
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.

    – Markieren Sie Lösegeld

    11. Februar 2021 um 18:38 Uhr

Benutzeravatar von meck373
meck373

Sie müssen von wb nach w wechseln:

def __init__(self):
    self.myCsv = csv.writer(open('Item.csv', 'wb')) 
    self.myCsv.writerow(['title', 'link'])

Zu

def __init__(self):
    self.myCsv = csv.writer(open('Item.csv', 'w'))
    self.myCsv.writerow(['title', 'link'])

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

Benutzeravatar von Shiv Buyya
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


Benutzeravatar von Freddy Mcloughlan
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


Benutzeravatar von Matan Hugi
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')

1443480cookie-check“TypeError: a bytes-like object is required, not ‘str'” beim Umgang mit Dateiinhalten in Python 3

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy