'str'对象没有属性'decode'。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])')

我只选择第一封电子邮件。如何全部选择?

Answers:


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
马丁·彼得斯

2
@devinbost:但是,通常最好在靠近数据源的地方解码,通常您会确切地知道自己拥有什么。
马丁·彼得斯

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或任何其他编码,将可以完成这项工作
Alex

20
这没用。您正在编码为UTF-8,然后将结果字节解码为UTF-8,最终从您开始的地方开始。您使CPU保持温暖,没有其他好处。
马丁·彼得斯

1
@MartijnPieters“结束了,你开始” -不,如果你有你的字符串转义序列,例如:“解码()\ u0159'.encode()。‘>>> R’
彼得·

1
@Peter:不,您不需要为此进行编码或解码。'\u0159'打印完全相同的输出。您正在将字符串文字语法与值的规范表示混淆。
马丁·彼得斯

2
您可以直接使用,无需编码,然后再次解码。
Aditya

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

我那么爱你!
Gal Shahar

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替代项,那么两者都会失败。
马丁·彼得斯

1
没错,这个特定问题确实已经存在str。这个答案可能对将来可能具有字节数组的人仍然有用(这是我最初偶然发现这篇文章时遇到的问题)。
Broper

我不确定您是如何迷失了这篇文章的,但是,因为它my_byte_str.decode存在且有效,并且不会在问题中抛出异常。
马丁·彼得斯


0

其他答案有点暗示它,但是问题可能出自于​​期望一个字节对象。在Python 3中,当您有一个类字节对象时,解码有效。在解码之前运行编码可能会“解决”问题,但这是无用的一对操作,将问题提示给上游。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.