NameError en Python : d'où vient l'erreur et comment la corriger

NameError survient quand Python rencontre un nom qu'il ne connaît pas : variable non définie, faute de frappe, import oublié.
5 min de lecture
Believemy logo

Définition

Le script tournait très bien jusqu'à cette ligne, et voilà que Python s'arrête net en évoquant un nom qu'il ne reconnaît pas. C'est exactement ce que signale NameError : au moment d'exécuter cette ligne précise, l'interpréteur cherche une variable, une fonction ou un module portant ce nom, et ne trouve rien nulle part dans le programme.

La différence avec une SyntaxError se sent tout de suite à l'usage. Une erreur de syntaxe empêche même le fichier de démarrer, parce que sa forme est invalide avant toute exécution. Une NameError, elle, laisse le programme tourner normalement, parfois longtemps, avant de buter sur la ligne fautive : le code est parfaitement lisible, seul ce nom précis n'existe pas.

Voici la forme la plus courante du problème, une simple variable mal recopiée :

PYTHON
print(totl)

# NameError: name 'totl' is not defined. Did you mean: 'total'?

Depuis la version 3.10, Python ajoute souvent cette suggestion entre parenthèses. Il compare le nom fautif à ceux qui existent déjà dans le programme et propose le plus proche, ce qui règle la moitié des cas sans même avoir besoin de relire tout le fichier.


Les quatre causes

Ce message unique recouvre en réalité quatre situations bien différentes, et savoir laquelle est en cause fait gagner un temps précieux. Le tableau suivant résume comment reconnaître chacune d'un coup d'œil, avant de s'attarder sur la plus piégeuse.

CauseSigne distinctif
Faute de frappeLe nom suggéré ressemble au vôtre
Module non importéLe nom est celui d'une bibliothèque
Variable définie dans une autre fonctionLe nom existe ailleurs dans le fichier
Variable créée dans une branche non priseLe programme marche parfois

Les deux premières causes se corrigent en quelques secondes une fois repérées : on corrige l'orthographe, ou on ajoute l'import manquant en tête de fichier. La troisième demande simplement de se souvenir qu'une fonction ne voit jamais les variables d'une autre fonction, même voisine : chacune vit dans son propre espace.

La quatrième cause mérite qu'on s'y attarde, parce qu'elle ne se manifeste pas à chaque exécution. Une variable affectée uniquement à l'intérieur d'un if n'existe que si la condition a été vraie ce jour-là. Le programme peut donc fonctionner sans accroc des dizaines de fois de suite, puis s'arrêter net le jour où les données empruntent l'autre chemin.

PYTHON
if solde > 0:
    message = "Crédit disponible"

print(message)   # NameError si le solde est nul
Attention

Ce genre de NameError passe souvent les tests sans encombre, parce que les jeux de données de test tombent rarement sur le cas limite. Il refait surface en production, sur la première donnée réelle qui emprunte la branche restée invisible jusque là.

Le remède consiste à donner une valeur par défaut à la variable avant la condition, ou à fermer la structure par un else qui couvre systématiquement tous les cas restants.


Sa cousine, UnboundLocalError

Une variante existe, encore plus déroutante, parce qu'elle touche une variable qui semble déjà exister sous vos yeux. Lorsqu'une fonction affecte une variable n'importe où dans son corps, Python décide que cette variable est locale à la fonction entière, y compris sur les lignes qui précèdent l'affectation elle même. La lire avant cette ligne déclenche alors une UnboundLocalError, même si une variable du même nom existe bel et bien au niveau du module.

PYTHON
compteur = 0

def incrementer():
    print(compteur)   # UnboundLocalError, et non 0
    compteur = compteur + 1

Rien, à la lecture de print(compteur), ne laisse deviner le problème : la variable globale vaut bien 0. C'est la ligne suivante, celle qui affecte compteur, qui transforme rétroactivement tout le corps de la fonction en zone locale, du début jusqu'à la fin.

Bon à savoir

Pour lire et modifier une variable globale depuis l'intérieur d'une fonction, il faut la déclarer avec global avant de s'en servir. Sans cette déclaration, toute affectation dans le corps de la fonction crée une variable locale distincte, même si elle porte le même nom qu'une variable du module.


Le diagnostic en trois secondes

Le message donne toujours le nom fautif entre guillemets, ce qui simplifie beaucoup la suite. Trois vérifications rapides suffisent, dans cet ordre : le nom est-il bien orthographié partout où il apparaît, l'import correspondant se trouve-t-il en tête de fichier, et la variable est-elle définie sur tous les chemins qui mènent jusqu'à cette ligne.

Si les trois vérifications ne donnent rien, il reste le cas de la portée : la variable existe bien quelque part, mais dans une autre fonction que celle qui la cherche. Deux fonctions ne partagent rien, et il faut alors passer la valeur en argument puis la renvoyer avec return.


Questions fréquentes

Question

Quelle différence avec AttributeError ?

NameError porte sur un nom que Python ne trouve nulle part dans le programme, alors qu'une AttributeError porte sur un objet bien connu auquel on demande quelque chose qu'il ne possède pas. Le premier message parle d'un nom introuvable, le second d'un objet précis et d'un attribut qui lui manque.

Question

Pourquoi ma variable de boucle n'existe-t-elle plus après coup ?

Si la séquence parcourue était vide, la boucle n'a fait aucun tour, et la variable qui aurait dû naître à l'intérieur n'a donc jamais été créée. Sur une séquence non vide en revanche, elle survit tranquillement à la boucle et conserve la dernière valeur qu'elle a prise.

Question

Comment repérer ces erreurs avant même l'exécution ?

Un éditeur correctement configuré pour Python souligne les noms inconnus au fur et à mesure de la frappe, et les outils d'analyse statique les signalent sur l'ensemble d'un projet en quelques secondes. C'est le genre de faute qu'aucune équipe ne devrait découvrir en production.

Termes connexes

Découvrez notre glossaire Python

Parcourez les termes et définitions les plus couramment utilisés dans le domaine du développement avec Python.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.