3. Erreurs courantes en Python#
Marc BUFFAT, dpt mécanique, Université Lyon 1
L’erreur est une formidable opportunité d’apprentissage
import numpy as np
3.1. Rappel de la méthodologie du calcul scientifique#
méthode scientifique d’utilisation d’un outil numérique
analyse du problème pour définir ce que l’on doit faire (analyse)
définir la manière dont on doit le faire (algorithme)
mise en oeuvre sur ordinateur (programmation)
vérification / validation de la méthode (validation)
analyse « critique » des résultats
qualités nécessaires !!!
rigueur dans l’analyse algorithmique
rigueur dans la programmation
rigueur dans la validation
3.2. Que faire en cas d’erreur#
Si vous suivez la démarche précédente et faites preuve de rigueur, alors la recherche d’erreurs se limite souvent à la recherche d’erreurs de syntaxe.
Les erreurs (de syntaxe) en programmation sont récurrentes. Avec de la méthode ce sont les erreurs les plus simples à corriger. C’est l’objectif principal de ce notebook.
Attention cependant, l’absence d’erreurs de syntaxe ne garantie aucunement que résultat fournit par le programme est correcte, car il existe un autre type d’erreur: l’erreur algorithmique, qui consiste à utiliser la mauvaise méthode (algorithme) pour résoudre le problème. Seule une analyse du problème avec des tests et des validations permettra de trouver ce type d’erreur.
3.2.1. Règles générales#
Lorsqu’une erreur (de syntaxe) est détectée par l’interpréteur Python, un message d’erreur est affichée, en général en anglais et sur plusieurs lignes (Traceback). Quelles sont les informations importantes:
la ligne où l’erreur est détectée est indiquée avec une flèche
--->
avec un numéro de lignele dernier message d’erreur (en générale en anglais) qui indique le type d’erreur. C’est la dernière ligne affichée. C’est ce message qu’il faut comprendre, les autres messages sont en général moins importants.
Avec ces 2 éléments, on peut commencer à chercher l’origine de l’erreur.
On commence par chercher l’erreur de syntaxe sur la ligne indiquée par la flèche
--->
.Si la syntaxe est correcte, alors on remonte les lignes de code précédentes, car l’erreur peut être due à une erreur induite par les instructions précédentes.
Si on ne trouve pas, on vérifie chaque étape en affichant la valeur des variables avec une instruction
print
3.3. Erreurs sur l’exécution du notebook#
3.3.1. utiliser bouton Exécuter
ou Run
#
Exécuter toujours tout le notebook depuis le début (en appuyant sur le bouton Executer ou Run)
En particulier certaines cellules servent à l’initialisation. Les erreurs suivantes sont liés à la non exécution des cellules en début de notebook
NameError Traceback (most recent call last)
<ipython-input-38-3daac93200e0> in <module>
----> 1 printmd("### Exercice test: écrire une fonction func t.q.")
2 nom = Exos[0]
3 get_ipython().system('test_exo -e $nom')
NameError: name 'printmd' is not defined
NameError Traceback (most recent call last)
<ipython-input-50-e53591bcd8b5> in <module>
----> 1 assert(check_function(func,Exos[0]))
2 Note_exos[0] = 1
3 print("Tests de validation OK! note =",sum(Note_exos)," sur",len(Note_exos))
NameError: name 'check_function' is not defined
3.3.2. Exécuter les cellules dans l’ordre#
et attention au nom des variables !!!
3.3.3. Suivre les instructions à la lettre!#
3.3.4. Executer toutes les cellules (ne pas en omettre)#
3.3.5. Bien comprendre la notation de variable#
variable case mémoire permettant de stocker une valeur
une variable doit être définie (avec une affectation) avant utilisation
l’affectation définie le type de la variable
x = 1 # création variable x entiere x = x + 1 # on modifie la variable x x = '1' # on a crée une nouvelle variable car on a changé le type
3.3.6. Bien comprendre la notion de fonction#
une fonction est un algorithme avec:
des données qui sont les arguments de la fonction
un résultat qui est la valeur de retour
les variables utilisées dans une fonction sont des variables locales
def ma_fonction(a,b, c): # a, b, c dont les données : arguments mean = (a*b*c)**(1./3.) # mean est une variable locale return mean # renvoie le résultat avec return # utilisation m1 = ma_fonction(1.,2.,3.) # appel de la fonction avec des valeurs numériques m2 = ma_fonction(m1, 2*m1 +1, 4.) # appel de la fonction avec des variables
3.4. Erreurs de syntaxe courantes#
3.4.1. Erreur d’indentation#
IndentationError: unexpected indent
IndentationError: expected an indented block
IndentationError: unindent does not match any outer indentation level
indique que l’instruction ne respecte pas les règles d’indentation de Python.
En particulier, les instructions doivent toutes commencées en colonne 1 (sans espace avant) sauf pour délimiter des blocs de code, comme:
les boucles
for
les tests conditionnels
if
la définition de fonction
def
3.4.1.1. exemples: IndentationError#
corriger les erreurs suivantes
a = 2
b = 3
File "/tmp/ipykernel_22122/999538517.py", line 2
b = 3
^
IndentationError: unexpected indent
somme = 0
for i in range(5):
somme = somme + i*i
File "/tmp/ipykernel_22122/633187784.py", line 3
somme = somme + i*i
^
IndentationError: expected an indented block after 'for' statement on line 2
i = 2
if i %2 :
print("i," est paire")
File "/tmp/ipykernel_22122/3307353396.py", line 3
print("i," est paire")
^
SyntaxError: unterminated string literal (detected at line 3)
def Somme(n):
s = 0
for i in range(5):
s = s + i*i
return s
File "<tokenize>", line 5
return s
^
IndentationError: unindent does not match any outer indentation level
3.4.2. Utilisation d’un variable non définie#
NameError: name 'X' is not defined
indique que l’on utilise une variable, ici X
qui n’a pas été définie.
rappel on ne peut pas utiliser de variables que l’on a pas définie précédemment avec une instruction d’affectation.
Cette erreur peut indiquer que l’on a pas utilisé la bonne variable
3.4.2.1. exemples : NameError#
corriger les erreurs suivantes
x = 1
x = X + 1
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/tmp/ipykernel_22122/4070494698.py in <cell line: 2>()
1 x = 1
----> 2 x = X + 1
NameError: name 'X' is not defined
for i in range(5):
ss = ss + i**3
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/tmp/ipykernel_22122/2188933506.py in <cell line: 1>()
1 for i in range(5):
----> 2 ss = ss + i**3
NameError: name 'ss' is not defined
3.4.3. Erreur de syntaxe#
SyntaxError: invalid syntax
cette erreur générique peut indiquer:
l’oublie d’un symbole “:” pour définir le début d’un bloc:
test
if
, bouclefor
ou définition de fonctiondef
la confusion d’opérateur: par exemple l’affectation
=
et l’égalité==
l’oublie de parenthèses
SyntaxError: EOL while scanning string literal
erreurs de délimiteur de chaîne de caractères
3.4.3.1. exemples : syntaxError#
corriger les erreurs suivantes
x = -1
if x > 0
print(x," est positif")
File "/tmp/ipykernel_22122/202564168.py", line 2
if x > 0
^
SyntaxError: expected ':'
def Somme(n)
s = 0
for i in range(5)
s = s + i*i
return s
File "/tmp/ipykernel_22122/4055143042.py", line 1
def Somme(n)
^
SyntaxError: expected ':'
x = 2
if x = 3 :
print(X,' est égale à 3')
File "/tmp/ipykernel_22122/2340081816.py", line 2
if x = 3 :
^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
s =0.5
x = round(2*(s+1)
print("x=",x)
File "/tmp/ipykernel_22122/2695908581.py", line 2
x = round(2*(s+1)
^
SyntaxError: '(' was never closed
message = "Python est facile à apprendre
print(message)
File "/tmp/ipykernel_22122/957600211.py", line 1
message = "Python est facile à apprendre
^
SyntaxError: unterminated string literal (detected at line 1)
3.4.4. Erreur de type#
TypeError: 'list' object is not callable
TypeError: 'numpy.ndarray' object is not callable
utilisation de ( )
à la place de [ ]
dans une liste ou un tableau numpy
IndexError: index 3 is out of bounds for axis 0 with size 3
IndexError: list index out of range
utilisation d’un indice en dehors des limites d’une liste ou d’un tableau
TypeError: 'int' object is not iterable
utilisation d’un entier à la place d’une liste ou d’un tableau (itérable)
3.4.4.1. exemples : TypeError#
corriger les erreurs suivantes
X = [ 1, 2, 3 ]
X(0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_22122/942919447.py in <cell line: 2>()
1 X = [ 1, 2, 3 ]
----> 2 X(0)
TypeError: 'list' object is not callable
X = np.array([1,2,3])
X(0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_22122/84339662.py in <cell line: 2>()
1 X = np.array([1,2,3])
----> 2 X(0)
TypeError: 'numpy.ndarray' object is not callable
X = np.array([1,2,3])
X[3]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
/tmp/ipykernel_22122/4125558170.py in <cell line: 2>()
1 X = np.array([1,2,3])
----> 2 X[3]
IndexError: index 3 is out of bounds for axis 0 with size 3
X = [ 1, 2, 3 ]
X[3]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
/tmp/ipykernel_22122/2918567873.py in <cell line: 2>()
1 X = [ 1, 2, 3 ]
----> 2 X[3]
IndexError: list index out of range
for i in 8:
print(i)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_22122/1066743296.py in <cell line: 1>()
----> 1 for i in 8:
2 print(i)
TypeError: 'int' object is not iterable
3.4.4.2. autres exemples#
ValueError Traceback (most recent call last)
<ipython-input-83-b474eb3d7114> in <module>
8 cours_id.append(cours_info[0].strip())
9 cours_titre.append(cours_info[1].strip())
---> 10 cours_ects.append(int(cours_info[2].strip()))
11 cours_semestre.append(int(cours_info[3].strip()))
ValueError: invalid literal for int() with base 10: '6 ECTS'
3.4.5. Erreur d’entrée/sortie ES#
OSError: file not found
FileNotFoundError: [Errno 2] No such file or directory
PermissionError: [Errno 13] Permission denied:
on essaye de lire des données dans un fichier qui n’existe pas, ou on a pas les droits d’accès au contenu du ficgier en lecture ou en écriture
3.4.5.1. exemples : IOError#
corriger les erreurs suivantes
Tab=np.random.rand(4,5)
np.savetxt('test.dat',Tab)
F1 = open('Test.dat')
F1.close()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
/tmp/ipykernel_22122/1789518339.py in <cell line: 3>()
1 Tab=np.random.rand(4,5)
2 np.savetxt('test.dat',Tab)
----> 3 F1 = open('Test.dat')
4 F1.close()
FileNotFoundError: [Errno 2] No such file or directory: 'Test.dat'
Tab1 = np.loadtxt('Test.dat')
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
/tmp/ipykernel_22122/806968169.py in <cell line: 1>()
----> 1 Tab1 = np.loadtxt('Test.dat')
~/venvs/jupyter/lib/python3.10/site-packages/numpy/lib/npyio.py in loadtxt(fname, dtype, comments, delimiter, converters, skiprows, usecols, unpack, ndmin, encoding, max_rows, quotechar, like)
1316 delimiter = delimiter.decode('latin1')
1317
-> 1318 arr = _read(fname, dtype=dtype, comment=comment, delimiter=delimiter,
1319 converters=converters, skiplines=skiprows, usecols=usecols,
1320 unpack=unpack, ndmin=ndmin, encoding=encoding,
~/venvs/jupyter/lib/python3.10/site-packages/numpy/lib/npyio.py in _read(fname, delimiter, comment, quote, imaginary_unit, usecols, skiplines, max_rows, converters, ndmin, unpack, dtype, encoding)
953 fname = os.fspath(fname)
954 if isinstance(fname, str):
--> 955 fh = np.lib._datasource.open(fname, 'rt', encoding=encoding)
956 if encoding is None:
957 encoding = getattr(fh, 'encoding', 'latin1')
~/venvs/jupyter/lib/python3.10/site-packages/numpy/lib/_datasource.py in open(path, mode, destpath, encoding, newline)
191
192 ds = DataSource(destpath)
--> 193 return ds.open(path, mode, encoding=encoding, newline=newline)
194
195
~/venvs/jupyter/lib/python3.10/site-packages/numpy/lib/_datasource.py in open(self, path, mode, encoding, newline)
531 encoding=encoding, newline=newline)
532 else:
--> 533 raise FileNotFoundError(f"{path} not found.")
534
535
FileNotFoundError: Test.dat not found.
F1 = open('/etc/sudoers')
---------------------------------------------------------------------------
PermissionError Traceback (most recent call last)
/tmp/ipykernel_22122/275259291.py in <cell line: 1>()
----> 1 F1 = open('/etc/sudoers')
PermissionError: [Errno 13] Permission denied: '/etc/sudoers'
3.5. Points clés#
Les messages de « TRaceBack » peuvent sembler intimidants, mais ils nous donnent beaucoup d’informations utiles sur ce qui n’a pas fonctionné dans notre programme, y compris où l’erreur s’est produite et de quel type d’erreur il s’agissait.
Une erreur liée à la syntaxe du programme est appelée
SyntaxError
.Si le problème est lié à la façon dont le code est indenté, il sera alors appelé
IndentationError
.Une erreur
NameError
se produira si vous utilisez une variable qui n’a pas été définie (soit parce que vous vouliez utiliser des guillemets autour d’une chaîne, vous avez oublié de définir la variable, ou vous venez de faire une faute de frappe).Les listes, les dictionnaires ou les tableaux généreront des erreurs si vous essayez d’accéder à des éléments qui n’existent pas. Pour les listes ou les tableaux, ce type d’erreur est appelé
IndexError
pour les dictionnaires, cela s’appelle uneKeyError
.Essayer de lire un fichier qui n’existe pas vous donnera une erreur
IOError
. Essayer de lire un fichier ouvert en écriture, ou écrire dans un fichier ouvert en lecture, vous donnera également une erreurIOError
.
3.6. Erreurs algorithmiques#
L’erreur algorithmique consiste à utiliser la mauvaise méthode (algorithme) pour résoudre le problème en utilisant un programme sans erreurs de syntaxe. Seule une analyse du problème avec des tests et des validations permettra de trouver ce type d’erreur.
3.6.1. Exemple 1#
Calcul de la somme des carrés des nombres entiers de 1 à 10
Trouvez l’erreur ou les erreurs dans les programmes suivants
for i in range(10):
somme = 0
somme = somme + i**2
print("somme des carrés de 1 a 10: ",somme)
somme des carrés de 1 a 10: 81
3.6.2. Exemple 2#
Calcul du produit des nombres entiers de 1 à 10
Trouvez l’erreur ou les erreurs dans les programmes suivants
prod = 1
for i in range(10):
prod = prod*i
print("produit des entiers de 1 à 10: ",prod)
produit des entiers de 1 à 10: 0
3.6.3. Exemple 3#
Ecrire une fonction qui calcule le produit des carrés des n premiers entiers strictement positifs
def produit(n):
prod = 1
for i in range(n):
prod = prod*(i+1)**2
print(prod)
p3 = produit(3)
print("produit des carrées des 3 premiers entiers :",p3)
36
produit des carrées des 3 premiers entiers : None
3.6.4. Exemple 4#
Calcul de la somme des valeurs d’une liste
L = [1,2,3,4,5]
somme = 0
for i in range(5):
somme = somme + i
print("somme de la liste:",somme)
somme de la liste: 10
3.6.5. Exemple 5#
algorithme faux qui marche à peu près !!!!
trouvez l’erreur
# fonction a écrire
def func(chaine):
''' renvoie une chaîne contenant les 2 premiers et 2 derniers caractères,
ou une chaine vide si la longueur est < a 2 '''
resultat = chaine[0]+chaine[1]+chaine[-2]+chaine[-1]
if len(chaine)<2:
return ""
else:
return resultat
func('BonJOUR')
'BoUR'
func("B")
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
/tmp/ipykernel_22122/1787622538.py in <cell line: 1>()
----> 1 func("B")
/tmp/ipykernel_22122/1680185286.py in func(chaine)
3 ''' renvoie une chaîne contenant les 2 premiers et 2 derniers caractères,
4 ou une chaine vide si la longueur est < a 2 '''
----> 5 resultat = chaine[0]+chaine[1]+chaine[-2]+chaine[-1]
6 if len(chaine)<2:
7 return ""
IndexError: string index out of range
3.6.6. Exemple 6#
attention boucle infinie:
trouvez l’erreur
# ajoute l'élément 8 à malist
malist = [1, 2, 3, '4', [5, 'six'], [7]]
for i in malist:
malist.append(8)
# boucle infinie
malist
---------------------------------------------------------------------------
KeyboardInterrupt Traceback (most recent call last)
/tmp/ipykernel_22122/840302930.py in <cell line: 3>()
2 malist = [1, 2, 3, '4', [5, 'six'], [7]]
3 for i in malist:
----> 4 malist.append(8)
KeyboardInterrupt: