วัตถุ '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])')

ฉันกำลังเลือกอีเมลฉบับที่ 1 เท่านั้น ฉันจะเลือกทั้งหมดได้อย่างไร

คำตอบ:


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หรือการเข้ารหัสอื่น ๆ
Alex

20
นี่มันไร้ประโยชน์ คุณกำลังเข้ารหัส UTF-8 จากนั้นถอดรหัสไบต์ผลลัพธ์เป็น UTF-8 ซึ่งลงท้ายด้วยจุดเริ่มต้น คุณรักษาความอบอุ่นของ CPU โดยไม่มีประโยชน์อื่นใด
Martijn Pieters

1
@MartijnPieters "สิ้นสุดตำแหน่งที่คุณเริ่ม" - ไม่ใช่ถ้าคุณมีลำดับการหลีกเลี่ยงในสตริงของคุณตัวอย่างเช่น: >>> '\ u0159'.encode (). decode (). decode ()' ř '
Peter

1
@ Peter: ไม่คุณไม่จำเป็นต้องเข้ารหัสหรือถอดรหัสสำหรับสิ่งนั้น '\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

ฉันไม่คุ้นเคยกับไลบรารี แต่ถ้าปัญหาของคุณคือคุณไม่ต้องการอาร์เรย์ไบต์วิธีง่ายๆในการระบุประเภทการเข้ารหัสคือการส่งโดยตรง:

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

3

มันถอดรหัสแล้วใน Python3 ลองโดยตรงควรใช้งานได้


1
ขอบคุณ @Aditya เหตุผลที่ฉันมาที่นี่เป็นเพราะการเปลี่ยนรหัสด้วย 2to3
Jesse Reza Khorasanee

0

คำตอบอื่น ๆ เรียงลำดับของคำใบ้ที่มัน แต่ปัญหาอาจเกิดขึ้นจากการคาดหวังวัตถุไบต์ ใน Python 3 การถอดรหัสจะใช้ได้เมื่อคุณมีอ็อบเจกต์ของคลาสไบต์ การเรียกใช้การเข้ารหัสก่อนที่จะถอดรหัสอาจ "แก้ไข" ปัญหา แต่เป็นคู่การทำงานที่ไร้ประโยชน์ซึ่งจะแนะนำปัญหาที่เราอัปสตรีม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.