Das Objekt 'str' hat kein Attribut 'decode'. Python 3 Fehler?

182

Hier ist mein Code:

import imaplib
from email.parser import HeaderParser

conn = imaplib.IMAP4_SSL('imap.gmail.com')
conn.login('[email protected]', 'password')
conn.select()
conn.search(None, 'ALL')
data = conn.fetch('1', '(BODY[HEADER])')
header_data = data[1][0][1].decode('utf-8')

An dieser Stelle erhalte ich die Fehlermeldung

AttributeError: 'str' object has no attribute 'decode'

Python 3 hat keine Dekodierung mehr, habe ich recht? Wie kann ich das beheben?

Auch in:

data = conn.fetch('1', '(BODY[HEADER])')

Ich wähle nur die 1. E-Mail aus. Wie wähle ich alle aus?

Martijn Pieters
quelle

Antworten:

181

Sie versuchen, ein Objekt zu dekodieren, das bereits dekodiert ist . Du hast einstr , es besteht keine Notwendigkeit mehr, von UTF-8 zu dekodieren.

Lassen Sie einfach das .decode('utf-8')Teil fallen:

header_data = data[1][0][1]

Bei Ihrem fetch()Anruf fragen Sie explizit nur nach der ersten Nachricht. Verwenden Sie einen Bereich, wenn Sie weitere Nachrichten abrufen möchten. Siehe die Dokumentation :

Die folgenden message_set- Optionen für Befehle sind eine Zeichenfolge, die eine oder mehrere Nachrichten angibt , auf die reagiert werden soll. Dies kann eine einfache Nachrichtennummer ( '1'), ein Bereich von Nachrichtennummern ( '2:4') oder eine Gruppe nicht zusammenhängender Bereiche sein, die durch Kommas ( '1:3,6:9') getrennt sind. Ein Bereich kann ein Sternchen enthalten, um eine unendliche Obergrenze anzuzeigen ( '3:*').

Martijn Pieters
quelle
6
Gibt es eine einfache Möglichkeit, dies bedingt zu tun? (Ich möchte nur dekodieren, wenn die Nachricht verschlüsselt ist.)
devinbost
5
@devinbost: in Python 3? Testen Sie den Objekttyp oder das decodeAttribut oder fangen Sie einfach die Ausnahme ab. try: data = data.decode('...') except AttributeError: pass.
Martijn Pieters
2
@devinbost: Normalerweise ist es jedoch besser, wenn Sie näher an der Quelle Ihrer Daten dekodieren, wo Sie normalerweise genau wissen, was Sie haben.
Martijn Pieters
37

Beginnen Sie mit Python 3, alle Zeichenfolgen sind Unicode-Objekte.

  a = 'Happy New Year' # Python 3
  b = unicode('Happy New Year') # Python 2

Der vorherige Code ist derselbe. Also ich denke du solltest das entfernen .decode('utf-8'). Weil Sie das Unicode-Objekt bereits erhalten haben.

Neo Ko
quelle
37

Verwenden Sie es mit dieser Methode:

str.encode().decode()
Alireza
quelle
1
bytearray(str, 'encoding').decode('another_encoding')würde den Job machen, wenn Sie dekodieren müssen idnaoder eine andere Kodierung
Alex
20
Das ist nutzlos. Sie codieren in UTF-8 und dekodieren dann die resultierenden Bytes als UTF-8, bis Sie dort beginnen, wo Sie begonnen haben. Sie halten die CPU ohne weiteren Vorteil warm.
Martijn Pieters
1
@MartijnPieters "landen dort, wo Sie angefangen haben" - nicht, wenn Sie Escape-Sequenzen in Ihrer Zeichenfolge haben, zum Beispiel: >>> '\ u0159'.encode (). Decode ()' ř '
Peter
1
@Peter: Nein, dafür brauchen Sie keine Kodierung oder Dekodierung. '\u0159'druckt genau die gleiche Ausgabe. Sie verwechseln die String-Literal-Syntax mit der kanonischen Darstellung des Werts.
Martijn Pieters
2
Sie können direkt verwenden. Es ist nicht erforderlich, zu codieren und dann erneut zu decodieren.
Aditya
10

Für Python3

html = """\\u003Cdiv id=\\u0022contenedor\\u0022\\u003E \\u003Ch2 class=\\u0022text-left m-b-2\\u0022\\u003EInformaci\\u00f3n del veh\\u00edculo de patente AA345AA\\u003C\\/h2\\u003E\\n\\n\\n\\n \\u003Cdiv class=\\u0022panel panel-default panel-disabled m-b-2\\u0022\\u003E\\n \\u003Cdiv class=\\u0022panel-body\\u0022\\u003E\\n \\u003Ch2 class=\\u0022table_title m-b-2\\u0022\\u003EInformaci\\u00f3n del Registro Automotor\\u003C\\/h2\\u003E\\n \\u003Cdiv class=\\u0022col-md-6\\u0022\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003ERegistro Seccional\\u003C\\/label\\u003E\\n \\u003Cp\\u003ESAN MIGUEL N\\u00b0 1\\u003C\\/p\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003EDirecci\\u00f3n\\u003C\\/label\\u003E\\n \\u003Cp\\u003EMAESTRO ANGEL D\\u0027ELIA 766\\u003C\\/p\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003EPiso\\u003C\\/label\\u003E\\n \\u003Cp\\u003EPB\\u003C\\/p\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003EDepartamento\\u003C\\/label\\u003E\\n \\u003Cp\\u003E-\\u003C\\/p\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003EC\\u00f3digo postal\\u003C\\/label\\u003E\\n \\u003Cp\\u003E1663\\u003C\\/p\\u003E\\n \\u003C\\/div\\u003E\\n \\u003Cdiv class=\\u0022col-md-6\\u0022\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003ELocalidad\\u003C\\/label\\u003E\\n \\u003Cp\\u003ESAN MIGUEL\\u003C\\/p\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003EProvincia\\u003C\\/label\\u003E\\n \\u003Cp\\u003EBUENOS AIRES\\u003C\\/p\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003ETel\\u00e9fono\\u003C\\/label\\u003E\\n \\u003Cp\\u003E(11)46646647\\u003C\\/p\\u003E\\n \\u003Clabel class=\\u0022control-label\\u0022\\u003EHorario\\u003C\\/label\\u003E\\n \\u003Cp\\u003E08:30 a 12:30\\u003C\\/p\\u003E\\n \\u003C\\/div\\u003E\\n \\u003C\\/div\\u003E\\n\\u003C\\/div\\u003E \\n\\n\\u003Cp class=\\u0022text-center m-t-3 m-b-1 hidden-print\\u0022\\u003E\\n \\u003Ca href=\\u0022javascript:window.print();\\u0022 class=\\u0022btn btn-default\\u0022\\u003EImprim\\u00ed la consulta\\u003C\\/a\\u003E \\u0026nbsp; \\u0026nbsp;\\n \\u003Ca href=\\u0022\\u0022 class=\\u0022btn use-ajax btn-primary\\u0022\\u003EHacer otra consulta\\u003C\\/a\\u003E\\n\\u003C\\/p\\u003E\\n\\u003C\\/div\\u003E"""
print(html.replace("\\/", "/").encode().decode('unicode_escape'))
krishna chandak
quelle
Ich liebe dich so sehr!
Gal Shahar
8

Ich bin mit der Bibliothek nicht vertraut, aber wenn Ihr Problem darin besteht, dass Sie kein Byte-Array möchten, können Sie auf einfache Weise einen Codierungstyp direkt in einer Besetzung angeben:

>>> my_byte_str
b'Hello World'

>>> str(my_byte_str, 'utf-8')
'Hello World'
Broper
quelle
Sie haben zunächst kein bytesObjekt und str(bytes_object, codec)sind nur eine alternative Schreibweise für bytes_object.decode(codec). Beide scheitern, wenn Sie strstattdessen wirklich eine haben .
Martijn Pieters
1
Sie haben Recht, diese spezielle Frage hat bereits eine str. Diese Antwort könnte auch in Zukunft für Personen nützlich sein, die möglicherweise Byte-Arrays haben (dies war das Problem, mit dem ich konfrontiert war, als ich ursprünglich auf diesen Beitrag gestoßen bin).
Broper
Ich bin mir jedoch nicht sicher, wie Sie auf diesen Beitrag gestoßen sind, da er my_byte_str.decodeexistiert und funktioniert und die Ausnahme nicht in die Frage werfen wird.
Martijn Pieters
3

Es ist bereits in Python3 dekodiert. Versuchen Sie es direkt, es sollte funktionieren.

Aditya
quelle
1
Danke @Aditya Der Grund, warum ich hier angekommen bin, ist der Codewechsel mit 2to3
Jesse Reza Khorasanee
0

Andere Antworten deuten darauf hin, aber das Problem kann durch das Erwarten eines Byte-Objekts entstehen. In Python 3 ist die Dekodierung gültig, wenn Sie ein Objekt mit Klassenbytes haben. Das Ausführen der Codierung vor der Decodierung kann das Problem "beheben", aber es ist ein nutzloses Operationspaar, das das Problem uns vorgelagert vorschlägt.

Demongolem
quelle