Đối tượng 'str' không có thuộc tính 'giải mã'. Lỗi Python 3?


182

Đây là mã của tôi:

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

Tại thời điểm này tôi nhận được thông báo lỗi

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

Python 3 không giải mã được nữa, phải không? Làm thế nào tôi có thể sửa lỗi này?

Ngoài ra, trong:

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

Tôi chỉ chọn email đầu tiên. Làm thế nào để tôi chọn tất cả?

Câu trả lời:


181

Bạn đang cố gắng giải mã một đối tượng đã được giải mã . Bạn có một str, không cần phải giải mã từ UTF-8 nữa.

Đơn giản chỉ cần thả .decode('utf-8')phần:

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

Đối với fetch()cuộc gọi của bạn , bạn rõ ràng chỉ yêu cầu tin nhắn đầu tiên. Sử dụng một phạm vi nếu bạn muốn lấy thêm tin nhắn. Xem tài liệu :

Các tùy chọn message_set cho các lệnh bên dưới là một chuỗi chỉ định một hoặc nhiều thông điệp sẽ được hành động. Nó có thể là một số tin nhắn đơn giản ( '1'), một dãy số tin nhắn ( '2:4') hoặc một nhóm các phạm vi không liền kề được phân tách bằng dấu phẩy ( '1:3,6:9'). Một phạm vi có thể chứa dấu hoa thị để chỉ ra giới hạn trên vô hạn ( '3:*').


6
Có một cách đơn giản để làm điều này có điều kiện? (Tôi chỉ muốn giải mã nếu tin nhắn được mã hóa.)
devinbost

5
@devinbost: trong Python 3? Kiểm tra loại đối tượng hoặc decodethuộc tính, hoặc chỉ bắt ngoại lệ. try: data = data.decode('...') except AttributeError: pass.
Martijn Pieters

2
@devinbost: tuy nhiên, bạn thường giải mã tốt hơn gần hơn với nguồn dữ liệu của mình, nơi bạn thường sẽ biết chính xác những gì bạn có.
Martijn Pieters

37

Bắt đầu với Python 3, tất cả các chuỗi là đối tượng unicode.

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

mã trước là như nhau. Vì vậy, tôi nghĩ rằng bạn nên loại bỏ .decode('utf-8'). Bởi vì bạn đã có được đối tượng unicode.


37

Sử dụng nó theo phương pháp này:

str.encode().decode()

1
bytearray(str, 'encoding').decode('another_encoding')sẽ thực hiện công việc nếu bạn cần giải mã idnahoặc bất kỳ mã hóa nào khác
Alex

20
Điều này là vô ích. Bạn đang mã hóa thành UTF-8, sau đó giải mã các byte kết quả là UTF-8, kết thúc tại nơi bạn bắt đầu. Bạn đang giữ CPU ấm mà không có lợi ích nào khác.
Martijn Pieters

1
@MartijnPieters "kết thúc nơi bạn bắt đầu" - không phải nếu bạn có chuỗi thoát trong chuỗi của mình, ví dụ: >>> '\ u0159'.encode (). Giải mã ()' ř '
Peter

1
@Peter: không, bạn không cần mã hóa hoặc giải mã cho điều đó. '\u0159'in chính xác cùng một đầu ra. Bạn đang nhầm lẫn cú pháp chuỗi ký tự với biểu diễn chính tắc của giá trị.
Martijn Pieters

2
Bạn có thể trực tiếp sử dụng, Không cần phải mã hóa và sau đó giải mã lại.
Aditya

10

Đối với 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'))

Anh yêu em rất nhiều!
Gal Shahar

8

Tôi không quen thuộc với thư viện, nhưng nếu vấn đề của bạn là bạn không muốn một mảng byte, một cách dễ dàng là chỉ định một loại mã hóa theo cách truyền:

>>> my_byte_str
b'Hello World'

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

Họ không có một bytesđối tượng để bắt đầu, và str(bytes_object, codec)chỉ là một cách viết thay thế cho bytes_object.decode(codec). Cả hai đều thất bại nếu bạn thực sự có một strthay thế.
Martijn Pieters

1
Bạn nói đúng, câu hỏi cụ thể này đã có str. Câu trả lời này vẫn có thể hữu ích cho những người trong tương lai có thể có mảng byte (đây là vấn đề tôi gặp phải khi ban đầu tôi vấp phải bài đăng này).
Broper

Tôi không chắc chắn làm thế nào bạn vấp ngã trên bài đăng này, tuy nhiên, bởi vì my_byte_str.decodetồn tại và hoạt động, và sẽ không ném ngoại lệ trong câu hỏi.
Martijn Pieters

3

Nó đã được giải mã trong Python3, Hãy thử trực tiếp nó sẽ hoạt động.


1
Cảm ơn @Aditya Lý do tôi đến đây là vì chuyển đổi mã với 2to3
Jesse Reza Khorasanee

0

Các câu trả lời khác loại gợi ý về nó, nhưng vấn đề có thể phát sinh từ việc mong đợi một đối tượng byte. Trong Python 3, giải mã là hợp lệ khi bạn có một đối tượng của byte lớp. Chạy mã hóa trước khi giải mã có thể "khắc phục" sự cố, nhưng đó là một cặp thao tác vô dụng gợi ý vấn đề chúng tôi ngược dòng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.