HOWTO · Python

Corriger l'erreur str object has no attribute decode en Python

Ce tutoriel traite de l'erreur str has no attribute decode en Python.

Sur cette page

Si Python signale AttributeError: 'str' object has no attribute 'decode', la valeur sur laquelle decode() est appelé est du texte, et non des octets. En Python 3, supprimez cet appel si la valeur est déjà une str. Utilisez decode() uniquement sur des bytes que vous devez convertir en texte, et effectuez cette conversion à l’endroit où ces octets entrent dans votre programme.

Comprendre l’erreur 'str' object has no attribute 'decode'

Python 3 distingue les chaînes de texte des séquences d’octets. Une valeur str contient du texte Unicode ; une valeur bytes contient des octets bruts qui peuvent représenter du texte encodé. La méthode decode() s’applique aux octets : elle les interprète selon un encodage de caractères et produit une str. En Python 3, une chaîne n’est pas une suite d’octets encodés en attente de décodage.

Cette erreur se produit lorsque le code appelle decode() sur une valeur de type str. Par exemple, l’expression "Hello".decode("utf-8") tente d’appliquer une opération réservée aux octets à du texte. Python lève l’AttributeError signalée, car str ne possède pas de méthode decode. Cela arrive souvent lors du portage de code ancien de Python 2 vers Python 3, ou lorsqu’une bibliothèque a déjà décodé les données avant de les renvoyer.

Exécutez cet exemple minimal pour afficher l’erreur sous forme de texte sélectionnable :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

try:
    "Hello".decode("utf-8")
except AttributeError as error:
    print(f"{type(error).__name__}: {error}")
AttributeError: 'str' object has no attribute 'decode'

La question importante n’est donc pas de savoir quel encodage transmettre à decode(), mais de déterminer le type de la valeur actuelle et son origine. S’il s’agit de texte, utilisez-le comme tel. S’il s’agit de bytes, décodez-les une seule fois avec l’encodage indiqué par la source. N’ajoutez pas de conversion simplement pour faire disparaître l’erreur.

Choisir la bonne correction selon qu’il s’agit de texte ou d’octets

Si la valeur est déjà du texte, supprimez l’appel à .decode(...) et utilisez directement la chaîne. C’est la correction habituelle de l’erreur signalée. Par exemple, si un analyseur de réponse, un pilote de base de données ou une lecture de fichier en mode texte vous fournit une str, transmettez cette valeur à la fonction suivante sans la décoder de nouveau.

Exécutez cet exemple :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

message = "Hello, Python!"
print(message)
Hello, Python!

La correction essentielle consiste à transmettre directement la chaîne à print ; aucun aller-retour d’encodage n’est nécessaire. Appliquez la même modification à la ligne qui échoue : supprimez l’appel lui-même au lieu de le remplacer par une autre conversion.

encode() effectue la conversion inverse : cette méthode transforme le texte en octets à l’aide d’un encodage choisi. Utilisez-la lorsqu’une API, un format de fichier ou un protocole exige explicitement des octets. Encoder une chaîne puis décoder immédiatement ces octets pour retrouver le texte d’origine est redondant si aucune opération sur les octets n’a lieu entre les deux. Cela ne corrige pas réellement une incompatibilité de types et peut masquer le point où le texte devient des octets.

Choisissez l’opération en fonction du type et de l’étape suivante : conservez la str pour traiter du texte, appelez encode() lorsque des octets sont nécessaires, et appelez decode() lorsque des octets doivent devenir du texte. Le sens de la conversion compte : les encodages définissent la correspondance entre caractères et octets ; ils ne s’appliquent pas automatiquement à chaque chaîne.

Décoder les octets à la frontière d’entrée des données

Si l’inspection montre que l’entrée est un objet bytes, le décodage est approprié. Décodez-le une seule fois lorsqu’il entre dans la partie de votre programme qui traite du texte, en utilisant l’encodage indiqué par la source. UTF-8 est courant, mais le bon choix dépend du fichier, du service ou du protocole qui a produit les octets.

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

raw_data = b"caf\xc3\xa9"
text = raw_data.decode("utf-8")
print(repr(text))

Ici, raw_data contient les octets UTF-8 représentant café ; decode("utf-8") les convertit donc en chaîne. Le caractère non ASCII rend visible la frontière d’encodage : en UTF-8, il est représenté par plusieurs octets, mais constitue un seul caractère dans le texte obtenu. Pour un fichier, ouvrez-le en mode texte avec le bon encodage si vous souhaitez que Python décode son contenu pendant la lecture. Si vous lisez des données binaires ou recevez des octets d’un socket ou d’une bibliothèque, décodez cette valeur à la frontière d’entrée, avant de la transmettre au code qui traite du texte.

Une séquence d’octets vide est également une entrée valide. Cet exemple la convertit à la frontière d’entrée sans considérer l’absence de contenu comme un échec de décodage :

raw_data = b""
text = raw_data.decode("utf-8")
print(repr(text))
''

Traitez la chaîne vide obtenue selon la signification de l’absence de contenu dans votre application. À l’inverse, si les octets ne sont pas valides dans l’encodage déclaré, définissez explicitement une politique : par exemple, signaler une erreur de décodage ou utiliser une stratégie de remplacement documentée. Ne choisissez pas silencieusement un autre encodage dans le seul but de réussir le décodage.

Évitez de décoder les mêmes données à chaque appel de fonction. Une fois les données converties en str, les fonctions en aval doivent accepter du texte et ne pas rappeler decode(). Si une API en aval a besoin d’octets, encodez les données à la frontière de cette API. Des frontières de conversion clairement définies permettent de savoir quelle couche décide de l’encodage.

En résumé, les valeurs str de Python 3 sont du texte et ne possèdent pas de méthode decode(). Pour du texte, supprimez cet appel ; décodez les bytes une seule fois, au moment où les données encodées deviennent du texte. Vous corrigerez ainsi cette erreur précise tout en respectant la distinction entre le texte et sa représentation en octets.

Retrouver et corriger l’origine de la chaîne

Pour trouver la valeur à l’origine de l’échec, repérez dans la trace d’exécution la ligne indiquée et inspectez l’objet juste avant .decode(). Vérifiez son type avec type(value) ou isinstance(value, bytes). Un court diagnostic peut aider à suivre une chaîne de traitement complexe :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

value = "already text"
print(type(value).__name__)

Si le diagnostic indique str, supprimez l’appel à decode et remontez jusqu’à la fonction, au fichier ou à la réponse qui a produit la valeur. Vérifiez si la source renvoie déjà du texte décodé. S’il indique bytes, identifiez l’encodage utilisé par la source et décodez les données à cet endroit, avant de les traiter comme du texte. Ne déduisez pas le type du nom d’une variable comme raw_data : inspectez l’objet lui-même.

Lorsque des données passent par plusieurs fonctions auxiliaires, précisez leurs contrats : une fonction qui traite du texte doit recevoir une str, tandis qu’une fonction qui traite des octets doit recevoir des bytes. Une annotation de type telle que def parse_message(message: str) -> None: documente cette attente, mais les annotations ne convertissent pas les valeurs à l’exécution. Si une interface peut renvoyer l’un ou l’autre type, normalisez la valeur une seule fois à cette interface et gardez le reste du programme cohérent.

En résumé, les valeurs str de Python 3 sont du texte et ne fournissent pas de méthode decode(). Supprimez cet appel pour le texte ; décodez les bytes une seule fois, au moment où une entrée encodée devient du texte. Vous corrigerez ainsi l’erreur tout en préservant la distinction voulue entre texte et représentation en octets.