Об'єкт 'str' не має атрибута 'декодування'. Помилка Python 3?


182

Ось мій код:

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

в цей момент я отримую повідомлення про помилку

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

У Python 3 вже немає декодування, я прав? як я можу це виправити?

Також у:

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

Я вибираю лише перший електронний лист. Як вибрати всі?

Відповіді:


181

Ви намагаєтеся розшифрувати об’єкт, який уже розшифрований . У вас є str, більше не потрібно розшифровувати UTF-8.

Просто відкиньте .decode('utf-8')деталь:

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

Що стосується вашого fetch()дзвінка, ви явно просите лише перше повідомлення. Використовуйте діапазон, якщо хочете отримати більше повідомлень. Дивіться документацію :

message_set для команд нижче - це рядок із зазначенням одного або декількох повідомлень, щодо яких потрібно діяти. Це може бути простий номер повідомлення ( '1'), діапазон номерів повідомлень ( '2:4') або група неспоріднених діапазонів, розділених комами ( '1:3,6:9'). Діапазон може містити зірочку для позначення нескінченної верхньої межі ( '3:*').


6
Чи є простий спосіб зробити це умовно? (Я хочу розшифрувати лише якщо повідомлення закодовано.)
devinbost

5
@devinbost: у Python 3? Перевірте тип об'єкта або decodeатрибут, або просто виберіть виняток. try: data = data.decode('...') except AttributeError: pass.
Martijn Pieters

2
@devinbost: однак, вам зазвичай краще розшифрувати ближче до джерела своїх даних, де ви зазвичай точно знаєте, що у вас є.
Martijn Pieters

37

Почніть з Python 3, вся рядок є об’єктом unicode.

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

код раніше однаковий. Тому я думаю, що вам слід видалити .decode('utf-8'). Тому що ви вже отримали об'єкт unicode.


37

Використовуйте цей метод:

str.encode().decode()

1
bytearray(str, 'encoding').decode('another_encoding')зробив би цю роботу, якщо вам потрібно розшифрувати idnaабо будь-яке інше кодування
Алекс

20
Це марно. Ви кодуєте UTF-8, потім декодуєте отримані байти як UTF-8, і закінчуєтесь там, де ви почали. Ви тримаєте центральний процесор без жодної іншої користі.
Martijn Pieters

1
@MartijnPieters "закінчується там, де ви почали" - не, якщо у вашому рядку є послідовності втечі, наприклад: >>> '\ u0159'.encode (). Decode ()' ř '
Пітер,

1
@Peter: ні, для цього вам не потрібно кодування чи декодування. '\u0159'друкує точно такий же вихід. Ви плутаєте синтаксис прямого рядка з канонічним поданням значення.
Martijn Pieters

2
Ви можете безпосередньо використовувати, Не потрібно кодувати, а потім знову декодувати.
Адітя

10

Для 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'))

Я так тебе люблю!
Гал Шахар

8

Я не знайомий з бібліотекою, але якщо ваша проблема полягає в тому, що ви не хочете байтового масиву, один простий спосіб - вказати тип кодування прямо в складі:

>>> my_byte_str
b'Hello World'

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

У них немає bytesоб'єкта для початку, і str(bytes_object, codec)це лише альтернативна написання bytes_object.decode(codec). І те, і інше strне вдається, якщо натомість у вас є
Martijn Pieters

1
Ви маєте рацію, це питання вже є str. Ця відповідь все ж може бути корисною людям у майбутньому, які можуть мати масиви байтів (це питання, з яким я стикався, коли спочатку натрапив на цю посаду).
Бропер

Я не впевнений, як ви натрапили на цю посаду, однак, бо my_byte_str.decodeіснує і працює, і не викине винятку у питанні.
Martijn Pieters

3

Це вже розшифровано в Python3, Спробуйте безпосередньо, воно повинно працювати.


1
Дякую @Aditya Причина, що я приїхав сюди, - через переключення коду з 2to3
Jesse Reza Khorasanee

0

Інші відповіді начебто натякають на це, але проблема може виникнути в очікуванні байтового об’єкта. У Python 3 декодування дійсне, коли у вас є об'єкт байтів класу. Запуск кодування перед декодуванням може «виправити» проблему, але це марна пара операцій, яка пропонує нам проблему вище за течією.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.