Partage

Les erreurs courantes en Python

Évitons de nous répéter

Staff Le 23 septembre 2010 à 11:07:38

Salut.
Après quelques mois d'existence de ce forum, on peut faire le constat que pas mal de topics de résolution de problèmes tournent autour de la mauvaise compréhension des exceptions que Python peut lever. Je vous propose que l'on recense dans ce topic, une liste des erreurs très courantes que nous observons chez les débutants, ainsi que des explications claires de manière à les aider à apprendre de leurs erreurs.

Il serait possible, ainsi, de transformer ce topic en une sorte de FAQ : « Mon programme plante. Quelle est mon erreur ? Comment la corriger ? », ayant pour optique de guider les débutants vers des réactions plus matures (et d'éviter les bazillions de doublons sur le forum), et les faire gagner en autonomie.

Avant de recenser ces erreurs, commençons par apprendre à les « lire ».

Anatomie d'une exception Python



Lorsqu'un programme Python plante, c'est en général (si ce n'est toujours…) en raison d'une exception non gérée. Voici le genre d'affichage que cela produit dans la console :

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    test()
  File "test.py", line 3, in test
    print table[4]
IndexError: list index out of range


Ces erreurs affichées par Python se lisent de bas en haut.

La ligne la plus importante : la dernière.



Examinons la dernière ligne de l'exemple ci-dessus.

IndexError: list index out of range


Sur cette ligne, nous avons 2 informations.
La première, c'est le type d'exception qui s'est produit. Dans cet exemple, il s'agit d'une IndexError . C'est en fonction de ces types d'erreurs que les exceptions seront classées dans ce topic.
La seconde, c'est le message contenu dans cette exception. Au travers de ce message, Python nous donne des indications sur ce qui a provoqué l'erreur.

Les lignes précédentes : le « traceback »



Les lignes qui précèdent la dernière sont ce que l'on appelle le "traceback". C'est ce qui permet de trouver rapidement où s'est produite l'erreur. Ces lignes vont en général 2 par 2 :

File "test.py", line 3, in test
  print table[4]


La première ligne indique :
- le fichier dans lequel on se trouve,
- la ligne de ce fichier à laquelle s'est produite l'erreur,
- le nom de la fonction que l'on est en train d'exécuter.

La seconde ligne présente l'instruction qui a fait planter le programme.

Les paires de lignes qui précèdent celle-ci sont les appels de fonctions successifs qui ont mené l'interpréteur jusqu'à cette instruction.
Cela permet de savoir grosso-modo où en était votre programme dans son exécution avant qu'il ne plante.

J'ai identifié mon exception, que faire ?



Ce paragraphe consignera, au fur et à mesure les exceptions rencontrées couramment, et référencera les posts contenant les explications des participants. Classés par exception et par message.




Participer à ce topic



Afin de participer à ce topic, merci d'organiser vos posts de la manière suivante :

Titre : type de l'exception et message de Python

…suivi des explications sur :
- les cas où Python lève cette exception avec ce message, [obligatoire]
- que vérifier/corriger dans le code (en général), [obligatoire]
- quelques rappels sur les "bonnes pratiques" à adopter dans ces cas de figure. [optionnel]

Essayez de préciser la version de Python (si le comportement est différent entre 2.x et 3.x).

Pour reporter du code tapé dans le shell Python, utilisez de préférence la balise code avec l'attribut "pycon", adapté à l'affichage du shell Python :

<code type="pycon">
>>> a = 5
>>> a
5
</code>

résultat :
>>> a = 5
>>> a
5


Merci d'avance aux participants !
I programmed in Perl after it was cool · Venez aux JSDZ ! Hier la capitale, aujourd'hui la France, demain le monde ?
Publicité
Le 23 septembre 2010 à 11:07:38
Le 23 septembre 2010 à 13:00:35

Salut.
Je trouve que c'est une belle initiative.
Et je pense que l'on pourrait utiliser ce mini-tuto de Krankkatze sur les exceptions comme un support pour traiter les différentes exceptions.
Staff Le 23 septembre 2010 à 13:12:08

Oui, ça peut servir de base. (Merci d'avoir répondu, j'vais pouvoir commencer à ajouter du contenu sans attendre 24h :D ).

Mon idée de base était surtout de partir des erreurs "j'ai pas compris mon exception" les plus courantes dans le forum, mais on peut aussi essayer d'anticiper, quoi qu'il est moins évident dans ce cas de trouver le genre d'inattention "typique de débutant" provoquant l'exception en question.
Concrètement : on vient d'aider un Zér0 à résoudre un problème en étant très tenté de lui dire « mais enfin ! Il suffit de LIRE l'erreur », on remarque que cette exception n'est pas encore consignée ici. Hop ! On la rajoute, et la prochaine fois, on n'a plus qu'à renvoyer vers le lien de l'explication en question, de manière à ce que la personne cherche aussi à comprendre son erreur (ce qui est plus formateur) plutôt qu'on la résolve pour lui.
I programmed in Perl after it was cool · Venez aux JSDZ ! Hier la capitale, aujourd'hui la France, demain le monde ?
Le 23 septembre 2010 à 13:36:34

IndentationError



Exemple



>>> a=5
>>> if a>0:
... print "a est superieur a 0"
  File "<stdin>", line 2
    print "a est superieur a 0"
        ^
IndentationError: expected an indented block


Pourquoi Python lève cette exception ?



C'est tout simplement parce-que python demande lors des boucles (for, while, if, else), des fonctions, etc... des règles d'indentation.

Citation : wikipedia

L’indentation est l’action qui permet d’ajouter des caractères de tabulations ou d’espaces



La convention veut que l'indentation soit d'une longueur de 4 espaces. Voir PEP8

Il ne faut jamais mélanger une tabulation et espaces.

Comment modifier son code en conséquence?



En ajoutant simplement 4 espaces après la boucle :p

>>> a=5
>>> if a>0:
...     print "a est superieur a 0"
... 
a est superieur a 0


Waouhhh!!!! Ca fonctionne :D

Rappel



Si vous avez une exception de type IndentationError, c'est que vous avez simplement une erreur d'indentation.

Vérifiez que votre longueur d'indentation est identique dans tout votre code et que vous n'avez pas mélangé les tabulations et les espaces.

Astuce-Un moyen mnémotechnique



Souvenez-vous du code exemple

>>> a=5
>>> if a>0:


On remarque le (:) qui se trouve en fin de ligne et qui indique le début d'un bloc.

L'indentation commencera donc après cette ligne!

;)

Merci à Plug'n'Play 512 pour l'astuce, sympa!

Staff Le 23 septembre 2010 à 13:48:50

Merci fred. Je vais rajouter un texte pour le message sur la constance tabulation/espace. Je rajoute le lien en premier post.

SyntaxError: inconsistent use of tabs and spaces in indentation



Quand cette exception se produit-elle ?



Comme vous le savez, les blocs en Python sont gérés par l'indentation. Pour indenter un bloc, il est possible d'utiliser des tabulations ou des espaces. Python accepte tout cela, mais exige que vous soyez consistants dans votre manière d'indenter vos blocs.

Cela signifie que si vous choisissez d'indenter un bloc avec des espaces, tous les blocs de votre programme devront être indentés avec des espaces, sans tabulation. Si vous ne le faites pas, Python n'a plus moyen de comprendre votre code, et retourne cette erreur.

Comment réparer cette erreur ?



Sur n'importe quel éditeur de texte digne de ce nom, il existe une fonction "Rechercher/Remplacer". Utilisez-la pour rechercher les tabulations, et les remplacer par 4 espaces.

Rappel sur les bonnes pratiques de Python



Comme le conseille Guido van Rossum dans la PEP-8, il est fortement conseillé de toujours indenter votre code en utilisant 4 espaces. Vous pouvez pour cela régler votre éditeur de texte préféré, de manière à ce qu'il insère des espaces en lieu et place des tabulations.

Autre détail : pour que votre code soit plus lisible, il est conseillé que vous utilisiez tout le temps le même nombre d'espaces quel que soit le niveau d'indentation.
I programmed in Perl after it was cool · Venez aux JSDZ ! Hier la capitale, aujourd'hui la France, demain le monde ?
Le 23 septembre 2010 à 13:58:41

NameError


Exemple de code non fonctionnel


>>> func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'func' is not defined

Pourquoi python lève-t-il cette exception ?


Cette exception signifie que la fonction func n'a pas été définie, peut-être vous êtes-vous trompé dans le nom de la fonction, ou avez oublié d'importer un module. Elle est valable pour l'appel à tout type d'objet (variable, classe, etc.)

Comment modifier son code en conséquence ?


Définir la fonction func avant son utilisation:
>>> def func():
...     return 42
... 
>>> func()
42
Le 23 septembre 2010 à 14:35:21

ZeroDivisionError


Exemple de code non fonctionnel


>>> 50 / 0
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    50 / 0
ZeroDivisionError: int division or modulo by zero

Pourquoi Python lève t-il une exception?


Cette exception signifie que l'on essaye de diviser un nombre par zéro grâce à l'opérateur '/' (division) ou '%' (modulo). Or nous savons que cela est impossible.

Comment modifier son code en conséquence ?


Il faut s'efforcer à ne pas diviser un nombre par zéro, ou bien utiliser les blocs try/except:
try:
    50 / 0
except ZeroDivisionError:
    print("Vous ne pouvez pas diviser par zéro !")

Rappel sur les bonnes pratiques de Python


Vérifiez toujours de ne pas diviser un nombre par zéro, que se soit avec le modulo (%) ou le signe de la division (/).
Les blocs try/except sont vos amis; n'hésitez pas à vous en servir.
Staff Le 23 septembre 2010 à 15:17:28

NameError: name 'X' is not defined
(en utilisant la fonction input sous Python 2)



Exemple de code problématique



Voici un exemple de code sous Python 2.x
>>> nom = input("comment t'appelles-tu ? ")
comment t'appelles-tu ? NoHaR
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'NoHaR' is not defined


D'où vient cette erreur ?



Vous avez probablement dû étudier la fonction input dans un tutoriel abordant Python 3, mais voulu l'utiliser en Python 2. Malheureusement, cette fonction se comporte différemment entre les deux versions.

En Python 2, la fonction input va chercher à interpréter la saisie de l'utilisateur, plutôt que de la restituer sous forme d'une chaîne de caractères. Par exemple :
>>> resultat = input("entrez un calcul à effectuer :")
entrez un calcul à effectuer : 3 * 4 + 12 * 15.0
>>> resultat
192.0


Ainsi, si l'utilisateur retourne autre-chose qu'une expression que Python peut interpréter, ce dernier l'enverra ballader, conformément à la signification générale d'une NameError.

Comment y remédier ?



Sous Python 2, pour obtenir le même comportement que la fonction input de Python 3, il faut utiliser la fonction raw_input :

>>> nom = raw_input("comment t'appelles-tu ? ")
comment t'appelles-tu ? NoHaR
>>> nom
'NoHaR'


I programmed in Perl after it was cool · Venez aux JSDZ ! Hier la capitale, aujourd'hui la France, demain le monde ?
Le 23 septembre 2010 à 15:42:15

ImportError


Exemple de code non fonctionnel


>>> import module_inexistant
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_inexistant

Pourquoi python lève-t-il cette exception ?


Cette exception signifie que le module module_inexistant n'a pas été trouvé, qu'il n'existe pas ou que son répertoire n'a pas été répertorié.

Comment modifier son code en conséquence ?


Vérifier l'orthographe du nom du module, et aussi que son répertoire parent apparaît dans la liste sys.path .
Pour ce second cas :
>>> import sys
>>> sys.path
['', '/usr/lib/python26.zip', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload', '/usr/lib/python2.6/site-packages', '/usr/lib/python2.6/site-packages/PIL', '/usr/lib/python2.6/site-packages/gst-0.10', '/usr/lib/python2.6/site-packages/gtk-2.0', '/usr/lib/python2.6/site-packages/wx-2.8-gtk2-unicode']

Mon module module_inexistant étant dans le répertoire /repertoire/parent/de/mon/module , je l'ajoute :
>>> import sys
>>> sys.path.append('/repertoire/parent/de/mon/module')
>>> import module_inexistant
>>> module_inexistant.func()
42


(Mon message ne me paraît pas tout à fait clair, si vous avez des idées pour l'améliorer, je suis preneur)
Réponse à fred : oui, je me suis mal exprimé, je sautais la vérification et passais directement à l'ajout du répertoire s'il n'était pas présent.
Le 23 septembre 2010 à 16:55:33

Salut,

Suis à la demande de NoHar, je passe le sujet en post-it. Veillez à ce que sa qualité reste la même ^^
Le 23 septembre 2010 à 18:20:22

Citation : NoHaR


Cela signifie que si vous choisissez d'indenter un bloc avec 4 espaces, tous les blocs de votre programme devront être indentés de la même manière, 4 espaces par 4 espaces. Si vous ne le faites pas, Python n'a plus moyen de comprendre votre code, et retourne cette erreur.



Je pense que tu t'es mal exprimé, mais il est possible d'indenter différement chaques blocs, avec n'importe quel nombre d'espaces ou de tabulations (et pas un mélange des deux).

Exemple :
def func(n):
  if n > 0:
       print("Le nombre", n, "est positif.")
  elif n < 0:
           print("Le nombre", n, "est négatif.")
  else:
    print("Le nombre", n, "est nulle.")
Staff Le 23 septembre 2010 à 22:51:06

C'est vrai.
Bon, étant donné que je ne suis pas sur un PC, j'ai un peu la flemme de corriger ce soir, mais dès demain matin je préciserai mon post.

Soit dit en passant, il est quand même préférable de garder toujours la même longueur d'indentation, pour des raisons de lisibilité.

Edit : voilà, c'est corrigé.
I programmed in Perl after it was cool · Venez aux JSDZ ! Hier la capitale, aujourd'hui la France, demain le monde ?
Le 31 août 2011 à 22:16:15

Citation : nohar

Sur n'importe quel éditeur de texte digne de ce nom, il existe une fonction "Rechercher/Remplacer". Utilisez-la pour rechercher les tabulations, et les remplacer par 4 espaces.



Sur n'importe quel éditeur de texte digne de ce nom (dérivés de scintilla, etc) tu peux paramétrer le style d'indentation en fonction de l'extension de fichier. Donc pour les *.py il faut penser à mettre la largeur des tabs à 4 espaces. D'autre part sur scite (et autres) tu fais "indentation settings" et tu peux passer des espaces aux tabulations sans avoir à rechercher-remplacer...

Pour revenir au topic, une erreur courante en python est de ne pas coder en python mais en C, par exemple oublier d'utiliser itertools, enumerate, zip(), mettre un while au lieu d'un for, etc.
Le 23 novembre 2011 à 15:05:13

Citation : nohar


Tu as raison, je viens de remettre l'ancien topic sur lequel on s'attaquait à ces points-là en post-it de ce forum.




Je connaissais ce fil que tu avais ouvert mais je n'avais pas vu qu'il contenait un passage en revue d'exceptions courantes.

Perso, je n'aurais pas parlé d'exception, terme à la fois
-- trop commun ; en effet, cela réfère à une situation exceptionnelle, on pense à des inondations, courts-circuits, tremblement de terre alors qu'en fait en programmation le sens est assez différent, je dirais même que pour un programmeur en train d'écrire son programme, lever des exceptions est tout le contraire d'exceptionnel.
-- trop spécifique puisque il se réfère à un mécanisme spécialisé des exceptions de Python auquel le débutant confronté à un message d'erreur n'est pas forcément initié.



Je pense que ton fil peut être utile aux débutants et qu'il permet de débloquer un certain nombre de situations.

Toutefois, je pense que cela concerne des situations assez élémentaires ; la réalité est souvent plus complexe, par exemple, un NameError peut être levé de façon sournoise, par exemple lorqu'on se réfère à une varibale toto qui est définie au cours d'une partie du flux d'exécution (une condition if par exemple) et qui n'est pas visitée à chaque exécution. Assez souvent, les exceptions sont juste un artefact et témoignent en fait d'un bug de conception, algorithmique ou un manque de maîtrise des différents éléments (syntaxe, sémantique) du langage de programmation. Donc, je pense qu'il faut informer le débutant qu'hélas, savoir interpréter une exception rapportée dans un message d'erreur n'est souvent que le début d'un jeu de piste et pas la fin de l'histoire.
Staff Le 23 novembre 2011 à 16:35:50

Citation : candide

Perso, je n'aurais pas parlé d'exception, terme à la fois



OK. Dès que j'ai le temps je reformulerai le post originel, pour parler d'erreurs et de messages d'erreurs, tout en introduisant le terme "exception".

Citation : candide

Toutefois, je pense que cela concerne des situations assez élémentaires



Tu n'as pas tort. Ceci dit, je vois mal comment on pourrait s'attaquer à ce problème particulier, à moins de rédiger dans un post (référencé en premier post) une sorte de micro-tuto sur le sujet, accolé à la liste d'erreurs courantes, peut-être…

Si tu as des idées sur le sujet, elles sont les bienvenues.
I programmed in Perl after it was cool · Venez aux JSDZ ! Hier la capitale, aujourd'hui la France, demain le monde ?
Le 23 novembre 2011 à 18:19:51

Citation : nohar


Citation : candide

Toutefois, je pense que cela concerne des situations assez élémentaires



Tu n'as pas tort. Ceci dit, je vois mal comment on pourrait s'attaquer à ce problème particulier, à moins de rédiger dans un post (référencé en premier post) une sorte de micro-tuto sur le sujet, accolé à la liste d'erreurs courantes, peut-être…



Il faut surtout complètement repenser la conception des documents d'apprentissage des langages de programmation, vaste question ...


Citation : nohar


Si tu as des idées sur le sujet, elles sont les bienvenues.



Ce ne sont pas les idées qui me manquent mais plutôt le temps pour les mettre en oeuvre (bon, on en est tous là je suppose ;) ). La question de l'erreur touche à des domaines très différents. Les modes et les contenus d'apprentissage sont en partie responsables du fait que nous fassions des erreurs de programmation, comme je l'ai dit plus haut, les documents d'apprentissage ayant tendance à passer sous silence cette fraction très importante du temps où nous mettons au point notre code à corriger des erreurs pour nous présenter que la partie achevée.


Pour en revenir à la question de la chaîne d'erreur, un document d'apprentissage d'un débogueur en ligne ne serait-il pas une aide à ceux qui qui voudraient corriger plus facilement leurs programmes ? Au-delà de ça, un débogueur est un outil très utile pour chasser les erreurs bien sûr mais plus généralement pour apprendre à programmer.
Le 2 mai 2012 à 19:19:12

IOError : avec les fichiers



Exemple de code problématique


Voici un exemple de code en python 3.x :

monfichier=open("Fichier_quelconque.txt","r")
contenu=monfichier.read()
monfichier.close()
print(contenu)


L'interprétation d'un tel code retourne une erreur comme celle-ci :
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'Fichier_quelconque.txt'


D'où vient cette erreur ?


Dans l'exemple ci-dessus, le fichier "Fichier_quelconque.txt" ne se trouve pas dans le répertoire courant de l'interpréteur python (ou bien il n'existe tout simplement pas !). Il ne peut donc pas y accéder, et renvoie donc cette erreur...

Comment y remédier ?


Il suffit d'indiquer le chemin correct du fichier que l'on veut ouvrir.
  • Pour cela, on peut changer de répertoire courant avec la fonction chdir() du module os :
    from os import chdir
    chdir("/Chemin/du/répertoire/du/fichier")
    monfichier=open("Fichier_quelconque.txt","r")
    contenu=monfichier.read()
    monfichier.close()
    print(contenu)
    

  • Si l'on veut s'épargner une importation, on peut également renseigner directement le chemin correct du fichier dans la fonction open, qu'il soit relatif ou absolu :
    monfichier=open("/Chemin/du/répertoire/du/fichier/Fichier_quelconque.txt","r")
    contenu=monfichier.read()
    monfichier.close()
    print(contenu)
    


Rappel sur les bonnes pratiques de Python



La méthode la plus sûre et la plus efficace pour l'ouverture d'un fichier reste celle qui emploie les blocs try except ainsi que le mot clé with, de cette manière :
try:
    with open("Fichier_quelconque.txt") as f:
        print f.readlines()
except IOError:
    print ("Erreur !")


Merci à fred1599 pour ses commentaires avisés :)
Et voilà !
Le 17 avril 2013 à 14:04:04- Message modéré pour le motif suivant : Message complètement hors sujet

Bonjour,

Grand débutant en python je suis un tutoriel posté sur ce site.

J'arrive au chapitre 4 où l'in doit écrire un petit programme(pour déterminer si une année donnée est ou non bissextile).

Je reçoit toujours comme message d'erreur suite à la demande d'execution des 4 lignes de code :SyntaxError: multiple statements found while compiling a single statement

a=int(input("année="))

if a%400== 0 or (a%4==0 and a%100!=0):

print(a,"""est une année bissextile"""")

else:

print(a,"""n'est pas une année bissextile""")

SyntaxError: multiple statements found while compiling a single statement

Pourriez-vous m'aider ?

Merci d'avance

Lire quand même
Le 23 avril 2013 à 10:56:45- Message modéré pour le motif suivant : Crée un nouveau topic plutôt que de poster un HS dans celui-ci.

salut!

je sais que je suis hors sujet mais je n'ai pas trouvé le bon forum pour demander ceci alors voilà:

je  vais rester 6 jours chez mes grands-parents qui n'ont pas la bonne version d'idle (1.2.4)C

alors voilà: les réponses d'un "input" doivent TOUJOURS se faire entre guillemets:

Comment t'appelles-tu?Mika

ValueError

Restart:

Comment t'appelles-tu? 'Mika'

('Bonjour','Mika','!')

et en plus comme vous le voyez il n'est pas écrit comme habituellement: TOUT ce qui est entre les deux parenthèses inclues est écrit !

Alors si vous avez soi une façon de contrôler IDLE 1.2.4 ou un lien pour télécharger une nouvelle version (Pas plus grande que 3.2.2), s'il vous plaît, pensez à moi et aidez-moi!

-
Edité par zesuperboss le 27 avril 2013 à 15:39:58

Lire quand même
Le 25 avril 2013 à 21:31:13- Message modéré pour le motif suivant : Pareil que les deux précédents...

J'ai de la difficulté à utiliser GETSTATE et SETSTATE avec Pickle. Je travaille avec le livre de Vincent Le Goff mais je n'y comprend rien. Quelqu'un pourrait me donner un exemple simple à comprendre?
Lire quand même
Le 27 avril 2013 à 15:42:19- Message modéré pour le motif suivant : Merci de créer un nouveau topic pour une nouvelle demande d'aide

pouvez-vous me dire, s'il vous plaît, quelle est la différence entre les fonctions 'input' et 'raw_input' ?
Lire quand même

Les erreurs courantes en Python

× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
  • Editeur
  • Markdown