L'objet 'str' n'a pas d'attribut 'decode'. Erreur Python 3?

182

Voici mon code:

import imaplib
from email.parser import HeaderParser

conn = imaplib.IMAP4_SSL('imap.gmail.com')
conn.login('[email protected]', 'password')
conn.select()
conn.search(None, 'ALL')
data = conn.fetch('1', '(BODY[HEADER])')
header_data = data[1][0][1].decode('utf-8')

à ce stade, j'obtiens le message d'erreur

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

Python 3 n'a plus de décodage, n'est-ce pas? Comment puis-je réparer cela?

Aussi dans:

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

Je sélectionne uniquement le 1er e-mail. Comment tout sélectionner?

Martijn Pieters
la source

Réponses:

181

Vous essayez de décoder un objet qui est déjà décodé . Vous avez un str, il n'est plus nécessaire de décoder à partir de UTF-8.

Déposez simplement la .decode('utf-8')pièce:

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

Quant à votre fetch()appel, vous ne demandez explicitement que le premier message. Utilisez une plage si vous souhaitez récupérer plus de messages. Consultez la documentation :

Les options message_set des commandes ci-dessous sont une chaîne spécifiant un ou plusieurs messages sur lesquels agir. Il peut s'agir d'un simple numéro de message ( '1'), d'une plage de numéros de message ( '2:4') ou d'un groupe de plages non contiguës séparées par des virgules ( '1:3,6:9'). Une plage peut contenir un astérisque pour indiquer une limite supérieure infinie ( '3:*').

Martijn Pieters
la source
6
Existe-t-il un moyen simple de le faire sous condition? (Je ne veux décoder que si le message est encodé.)
devinbost
5
@devinbost: en Python 3? Testez le type d'objet ou l' decodeattribut, ou attrapez simplement l'exception. try: data = data.decode('...') except AttributeError: pass.
Martijn Pieters
2
@devinbost: cependant, il vaut généralement mieux décoder plus près de la source de vos données, où vous saurez généralement exactement ce que vous avez.
Martijn Pieters
37

Commencez par Python 3, toute la chaîne est un objet unicode.

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

le code avant est le même. Je pense donc que vous devriez supprimer le fichier .decode('utf-8'). Parce que vous avez déjà obtenu l'objet unicode.

Néo Ko
la source
37

Utilisez-le par cette méthode:

str.encode().decode()
Alireza
la source
1
bytearray(str, 'encoding').decode('another_encoding')ferait le travail si vous avez besoin de décoder idnaou de tout autre encodage
Alex
20
Cela ne sert à rien. Vous encodez en UTF-8, puis décodez les octets résultants en UTF-8, pour finir là où vous avez commencé. Vous gardez le CPU au chaud sans autre avantage.
Martijn Pieters
1
@MartijnPieters "finissant là où vous avez commencé" - pas si vous avez des séquences d'échappement dans votre chaîne, par exemple: >>> '\ u0159'.encode (). Decode ()' ř '
Peter
1
@Peter: non, vous n'avez pas besoin d'encodage ou de décodage pour ça. '\u0159'imprime exactement la même sortie. Vous confondez la syntaxe littérale de chaîne avec la représentation canonique de la valeur.
Martijn Pieters
2
Vous pouvez utiliser directement, il n'est pas nécessaire d'encoder puis de décoder à nouveau.
Aditya du
10

Pour 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'))
Krishna Chandak
la source
Je t'aime tellement!
Gal Shahar
8

Je ne suis pas familier avec la bibliothèque, mais si votre problème est que vous ne voulez pas de tableau d'octets, un moyen simple est de spécifier un type d'encodage directement dans un cast:

>>> my_byte_str
b'Hello World'

>>> str(my_byte_str, 'utf-8')
'Hello World'
Broper
la source
Ils n'ont pas d' bytesobjet pour commencer et ne str(bytes_object, codec)sont qu'une orthographe alternative bytes_object.decode(codec). Les deux échouent si vous avez vraiment un strfichier.
Martijn Pieters
1
Vous avez raison, cette question spécifique a strdéjà un . Cette réponse pourrait encore être utile aux personnes à l'avenir qui pourraient avoir des tableaux d'octets (c'était le problème auquel j'ai été confronté lorsque je suis tombé sur ce post).
Broper
Je ne sais pas comment vous êtes tombé sur ce post, car il my_byte_str.decodeexiste et fonctionne, et ne jettera pas l'exception dans la question.
Martijn Pieters
3

Il est déjà décodé en Python3, essayez directement cela devrait fonctionner.

Aditya
la source
1
Merci @Aditya La raison pour laquelle je suis arrivé ici est à cause du changement de code avec 2to3
Jesse Reza Khorasanee
0

D'autres réponses y font allusion, mais le problème peut provenir de l'attente d'un objet bytes. Dans Python 3, le décodage est valide lorsque vous avez un objet d'octets de classe. Lancer l'encodage avant le décodage peut "résoudre" le problème, mais c'est une paire d'opérations inutiles qui suggère le problème en amont.

démongolem
la source