Voici un complément un utile sur l’étude des erreurs.

"""On importe les bibliothèques scientifiques car elles seront utilisées ensuite"""
import numpy as np
import matplotlib.pyplot as plt

5. Comprendre ses erreurs#

Quand on écrit du code, on fait des erreurs. Ca arrive à tout le monde. Il y a deux types d’erreurs :

  • Les erreurs qui empêchent le code de s’exécuter correctement : Python renvoie alors un message d’erreur.

  • Les erreurs qui n’empêchent pas le code de s’exécuter mais qui font que le programme ne renvoie pas ce qui est attendu.

5.1. Python et les messages d’erreurs.#

5.1.1. Exemple basique#

Lorsqu’un script bute sur un erreur d’exécution. Python affiche un message :

L1 = np.array([1, 2, 3])
L2 = np.array([1, 2])

L3 = L1 + L2

a = 3 * 4

print(L3)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [2], line 4
      1 L1 = np.array([1, 2, 3])
      2 L2 = np.array([1, 2])
----> 4 L3 = L1 + L2
      6 a = 3 * 4
      8 print(L3)

ValueError: operands could not be broadcast together with shapes (3,) (2,) 

Pour comprendre et corriger son erreur, deux points sont importants :

  • L’endroit où l’erreur a été commise : ici ----> 6 L3 = L1 + L2. C’est à la ligne 6.

  • Le message d’erreur : ValueError: operands could not be broadcast together with shapes (3,) (2,) . Avec un peu de connaissance en anglais, on comprend que les deux vecteurs numpy n’ont pas la même taille (shape) et qu’on ne peut donc pas les sommer.

Dans la majorité des cas, ces deux éléments vont permettront de comprendre votre erreur.

5.1.2. Le cas d’erreur dans une fonction#

Il arrive que certaines erreurs se trouvent dans une fonction. Le message d’erreur est alors un peu plus compliqué :

def x_carre(x):
  return x ** 2

a = "r"

b = x_carre(a)

print(b)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [3], line 6
      2   return x ** 2
      4 a = "r"
----> 6 b = x_carre(a)
      8 print(b)

Cell In [3], line 2, in x_carre(x)
      1 def x_carre(x):
----> 2   return x ** 2

TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

Ici, Python signale deux endroits où il y a une erreur. L’explication est simple : ici le message est assez clair, l’opérateur puissance (**) ne peut s’appliquer entre une chaine de caractère str et un entier int (logique !!). Sauf que cette erreur se produit dans une fonction (x_carre). Python signale alors :

  • l’endroit où la fonction a été appelée b = x_carre(a)

  • l’endroit dans la fonction à l’erreur a été déclenchée (return x ** 2)

A vous de savoir si le problème est la définition de la fonction ou la manière de l’appeler. Ici c’est vraisemblablement la manière de l’appeler car on ne devrait pas chercher à calculer le carré d’une chaine de caractère !

Ce système est très efficace mais peut dérouter, surtout quand on utilise des fonctions déjà existantes qui sont souvent imbriquées. Un exemple ci-dessous.

L1 = np.array([1, 2, 3])
L2 = np.array([1, 2])

f, ax = plt.subplots()
ax.plot(L1, L2)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [4], line 5
      2 L2 = np.array([1, 2])
      4 f, ax = plt.subplots()
----> 5 ax.plot(L1, L2)

File D:\cedri\anaconda3\envs\prepa\lib\site-packages\matplotlib\axes\_axes.py:1662, in Axes.plot(self, scalex, scaley, data, *args, **kwargs)
   1419 """
   1420 Plot y versus x as lines and/or markers.
   1421 
   (...)
   1659 (``'green'``) or hex strings (``'#008000'``).
   1660 """
   1661 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-> 1662 lines = [*self._get_lines(*args, data=data, **kwargs)]
   1663 for line in lines:
   1664     self.add_line(line)

File D:\cedri\anaconda3\envs\prepa\lib\site-packages\matplotlib\axes\_base.py:311, in _process_plot_var_args.__call__(self, data, *args, **kwargs)
    309     this += args[0],
    310     args = args[1:]
--> 311 yield from self._plot_args(
    312     this, kwargs, ambiguous_fmt_datakey=ambiguous_fmt_datakey)

File D:\cedri\anaconda3\envs\prepa\lib\site-packages\matplotlib\axes\_base.py:504, in _process_plot_var_args._plot_args(self, tup, kwargs, return_kwargs, ambiguous_fmt_datakey)
    501     self.axes.yaxis.update_units(y)
    503 if x.shape[0] != y.shape[0]:
--> 504     raise ValueError(f"x and y must have same first dimension, but "
    505                      f"have shapes {x.shape} and {y.shape}")
    506 if x.ndim > 2 or y.ndim > 2:
    507     raise ValueError(f"x and y can be no greater than 2D, but have "
    508                      f"shapes {x.shape} and {y.shape}")

ValueError: x and y must have same first dimension, but have shapes (3,) and (2,)
../_images/complement_7_1.png

Pour corriger son erreur, il faut :

  • garder son calme !

  • chercher le message d’erreur (ici ValueError: x and y must have same first dimension, but have shapes (3,) and (2,))

  • chercher la partie du message d’erreur qui point vers votre code (on peut raisonnablement penser qu’il n’y a pas d’erreurs dans les fonctions des bibliothèques officielles). Ici ax.plot(L1, L2) : L1 et L2 n’ont pas la même taille, c’est là le problème.

5.1.3. Les parenthèses…#

Lorsqu’on écrit une formule un peu trop grosse, il arrive qu’on oublie de fermer une parenthèse.

u1 = 1
u2 = 0.1
v1 = 15
v2 = 14
a = v1 / v2
ua = a * np.sqrt((u1 / v1) ** 2 + (u2 / v2) ** 2



print(ua)
  Cell In [5], line 10
    print(ua)
    ^
SyntaxError: invalid syntax

Problèmes :

  • le message est peu verbeux (syntaxe invalide)

  • la ligne pointé par le message n’est pas la ligne où il y a une erreur !

En effet, Python ne se rend compte du problème de parenthèse mal fermée que lorsqu’il arrive sur une nouvelle instruction. C’est pourquoi, en cas d’erreur de syntaxe invalide, pensez aussi à vérifier l’écriture des lignes au dessus de l’endroit signalé par le message d’erreur.

5.2. Pas d’erreur mais…#

Attention

Ce n’est pas parce que l’interpréteur Python ne renvoie pas une erreur que votre programme est bon. Il peut faire des calculs et renvoyer des valeurs qui ne sont pas celles recherchées.

Tip

Prenez l’habitude de tester votre code sur des cas simples où vous connaissez les valeurs de retours attendues pour vérifier que votre programme fait bien ce qui est demandé (éviter les cas particuliers).