Obiekt „str” nie ma atrybutu „decode”. Błąd Pythona 3?


182

Oto mój kod:

import imaplib
from email.parser import HeaderParser

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

w tym momencie pojawia się komunikat o błędzie

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

Python 3 nie ma już dekodowania, mam rację? jak mogę to naprawić?

Także w:

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

Wybieram tylko pierwszy e-mail. Jak wybrać wszystko?

Odpowiedzi:


181

Próbujesz zdekodować obiekt, który został już zdekodowany . Maszstr , nie ma już potrzeby dekodowania z UTF-8.

Po prostu upuść .decode('utf-8')część:

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

Jeśli chodzi o Twój fetch()telefon, to wyraźnie prosisz tylko o pierwszą wiadomość. Użyj zakresu, jeśli chcesz pobrać więcej wiadomości. Zobacz dokumentację :

W message_set opcje do poleceń Poniżej znajduje się ciąg znaków określający jedną lub więcej wiadomości mają być wykorzystane. Może to być prosty numer wiadomości ( '1'), zakres numerów wiadomości ( '2:4') lub grupa nieciągłych zakresów oddzielonych przecinkami ( '1:3,6:9'). Zakres może zawierać gwiazdkę wskazującą nieskończoną górną granicę ( '3:*').


6
Czy istnieje prosty sposób, aby to zrobić warunkowo? (Chcę tylko zdekodować, jeśli wiadomość jest zakodowana.)
devinbost

5
@devinbost: w Pythonie 3? Przetestuj pod kątem typu obiektu lub decodeatrybutu lub po prostu złap wyjątek. try: data = data.decode('...') except AttributeError: pass.
Martijn Pieters

2
@devinbost: jednak zwykle lepiej jest dekodować bliżej źródła swoich danych, gdzie zwykle wiesz dokładnie, co masz.
Martijn Pieters

37

Zaczynając od Pythona 3, cały ciąg znaków jest obiektem Unicode.

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

kod przed jest taki sam. Więc myślę, że powinieneś usunąć .decode('utf-8'). Ponieważ masz już obiekt Unicode.


37

Użyj tej metody:

str.encode().decode()

1
bytearray(str, 'encoding').decode('another_encoding')wykona zadanie, jeśli potrzebujesz dekodować idnalub innego kodowania
Alex,

20
To jest bezużyteczne. Kodujesz do UTF-8, a następnie dekodujesz otrzymane bajty jako UTF-8, kończąc w miejscu, w którym zacząłeś. Utrzymujesz ciepło procesora bez żadnych innych korzyści.
Martijn Pieters

1
@MartijnPieters "kończy się tam, gdzie zacząłeś" - nie, jeśli w ciągu znaków występują sekwencje specjalne, na przykład: >>> '\ u0159'.encode (). Decode ()' ř '
Piotr

1
@Peter: nie, nie potrzebujesz do tego kodowania ani dekodowania. '\u0159'drukuje dokładnie to samo wyjście. Mylisz składnię literału ciągu znaków z kanoniczną reprezentacją wartości.
Martijn Pieters

2
Możesz bezpośrednio użyć, nie ma potrzeby kodowania, a następnie ponownego dekodowania.
Aditya,

10

W przypadku 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'))

Bardzo Cię kocham!
Gal Shahar

8

Nie znam biblioteki, ale jeśli Twoim problemem jest to, że nie chcesz tablicy bajtów, jednym prostym sposobem jest określenie typu kodowania bezpośrednio w rzutowaniu:

>>> my_byte_str
b'Hello World'

>>> str(my_byte_str, 'utf-8')
'Hello World'

Na początku nie mają bytesobiektu i str(bytes_object, codec)są po prostu alternatywną pisownią bytes_object.decode(codec). Oba zawodzą, jeśli naprawdę masz strzamiast tego.
Martijn Pieters

1
Masz rację, to konkretne pytanie strjuż ma. Ta odpowiedź może być nadal przydatna dla osób w przyszłości, które mogą mieć tablice bajtów (był to problem, z którym miałem do czynienia, gdy natknąłem się na ten post).
Broper

Nie jestem jednak pewien, jak trafiłeś na ten post, bo my_byte_str.decodeistnieje i działa, a wyjątku w pytaniu nie wrzucę.
Martijn Pieters

3

Jest już zdekodowany w Pythonie3, Spróbuj bezpośrednio, powinno działać.


1
Dzięki @Aditya Powodem, dla którego tu przybyłem, jest zmiana kodu za pomocą 2to3
Jesse Reza Khorasanee

0

Inne odpowiedzi trochę na to wskazują, ale problem może wynikać z oczekiwania obiektu bajtów. W Pythonie 3 dekodowanie jest poprawne, gdy masz obiekt klasy bajtów. Uruchomienie kodowania przed dekodowaniem może "naprawić" problem, ale jest to bezużyteczna para operacji, która sugeruje problem nam nadrzędnym.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.