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

最初のメールのみを選択しています。すべてを選択するにはどうすればよいですか?

回答:


181

すでにデコードされているオブジェクトをデコードしようとしています。がありますstr。UTF-8からデコードする必要はもうありません。

単に.decode('utf-8')部品を落とす:

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

あなたのためとしてfetch()呼び出しは、明示的にちょうど最初のメッセージを求めています。さらにメッセージを取得する場合は、範囲を使用します。ドキュメントを参照してください:

以下のコマンドのmessage_setオプションは、処理する1つ以上のメッセージを指定する文字列です。単純なメッセージ番号('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')。あなたはすでにユニコードオブジェクトを取得しているからです。


37

この方法で使用してください:

str.encode().decode()

1
bytearray(str, 'encoding').decode('another_encoding')デコードidnaまたはその他のエンコードが必要な場合に機能します
Alex

20
これは役に立たない。UTF-8にエンコードしてから、結果のバイトをUTF-8としてデコードし、最終的に開始した場所に到達します。CPUを暖かく保ち、他の利点はありません。
Martijn Pieters

1
@MartijnPieters "開始した場所で終了"-たとえば、文字列にエスケープシーケンスがある場合は、次のようになります。>>> '\ u0159'.encode()。decode()'ř '
Peter

1
@ピーター:いいえ、そのためのエンコードやデコードは必要ありません。'\u0159'まったく同じ出力を出力します。文字列リテラル構文を値の正規表現と混同しています。
Martijn Pieters

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

私はライブラリに精通していませんが、バイト配列が必要でないことが問題である場合、1つの簡単な方法は、キャストでエンコードタイプを直接指定することです。

>>> 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すでにあります。この回答は、バイト配列を持つ可能性のある将来の人々にとって依然として役立つ可能性があります(これは私が最初にこの投稿を偶然見つけたときに直面した問題でした)。
Broper

my_byte_str.decode存在して機能しているため、この投稿でどのようにつまずいたかはわかりません。質問で例外を​​スローしません。
Martijn Pieters


0

他の人はそれにヒントのような答えをしますが、問題はバイトオブジェクトを期待することから発生するかもしれません。Python 3では、クラスbytesのオブジェクトがある場合、decodeは有効です。デコードの前にエンコードを実行すると問題が「修正」される可能性がありますが、上流での問題を示唆するのは無意味な操作のペアです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.