3. Erreurs courantes en Python#

Marc BUFFAT, dpt mécanique, Université Lyon 1

python

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 !!!

    1. rigueur dans l’analyse algorithmique

    2. rigueur dans la programmation

    3. 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:

  1. la ligne où l’erreur est détectée est indiquée avec une flèche ---> avec un numéro de ligne

  2. le 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.

  1. On commence par chercher l’erreur de syntaxe sur la ligne indiquée par la flèche --->.

  2. 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.

  3. 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#

erreur

et attention au nom des variables !!!

3.3.3. Suivre les instructions à la lettre!#

erreur2

3.3.4. Executer toutes les cellules (ne pas en omettre)#

erreur4

erreur3

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:

  1. l’oublie d’un symbole “:” pour définir le début d’un bloc:

  • test if, boucle for ou définition de fonction def

  1. la confusion d’opérateur: par exemple l’affectation = et l’égalité ==

  2. l’oublie de parenthèses

SyntaxError: EOL while scanning string literal

  1. 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 une KeyError.

  • 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 erreur IOError.

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: 

3.7. FIN#