Marc BUFFAT

Professeur au département de Mécanique, Lyon 1 e-mail

Blog scientifique et pédagogique utilisant des notebooks IPython et Linux

cours en ligne INPROS: chapitre 11


In [4]:
%matplotlib inline
%autosave 300
from IPython.core.display import HTML,display
css_file = 'style.css'
HTML(open(css_file, "r").read())
Autosaving every 300 seconds
Out[4]:

Recherche d’erreurs (debugging)

LyonHPC LyonHPC
d’après le site [->http://phdcomics.com/comics.php]

Historique

Un bug informatique ou bogue est communément attribué au tout premier incident informatique qui a été causé par un insecte lors du développement du système informatique électromécanique à lampes Harvard Mark II en 1945.

Mark II         Bug

Cependant, le terme bug était déja utiliser pour désigner un défaut de conception depuis Thomas Edison en 1878.

Méthodologie

(voir aussi le cours MIT 6.00 “Introduction to computer science and programming” )

Les erreurs dans un programme (bogues ou bugs) sont introduites par le programmeur:

  • erreur de syntaxe
  • erreur de programmation
  • erreur algorithmique

objectifs du debugging

  • essayer d’obtenir un programme avec le moins d’erreurs possible (bug-free program)
  • et non pas éliminer rapidement une erreur
  • le debugging est très fortement associé à la validation

Dans le développement d’applications, la partie debugging et validation représente la part la plus importante.

démarche du debugging

  • démarche systématique basée sur la logique
  • outils d’aide au debugging = debugger OK
  • mais ce qui est le plus important est la méthode, plus que l’outil !
  • outil simple et efficace= insertion de print dans le code

méthode

  • recherche de bugs par dichotomie (binary search)
  • avec pour objectif non pas de trouver pourquoi le programme ne donne pas le bon résultat, mais de comprendre pourquoi le programme fonctionne de cette façon pour ensuite le corriger.
  • approche scientifique:
    • on fait une hypothèse
    • on choisit des données, et on fait des expériences numériques reproductibles pour tenter d’invalider l’hypothèse
    • raisonnement par dichotomie
      • hypothèse: telle partie du programme donne le résultat attendu
      • insertion de print pour tester l’hypothèse

Exemple de debugging

Voici un programme qui teste si la représentation base 2 d’un entier est un palindrome.

exemple:

  • n=9 en base 2 s’écrit 1001 et est donc un palindrome
  • n=12 en base 2 s’écrit 1100 et n’est pas un palindrome

principe de l’algorithme

n entier positif
conversion de n en base 2 sous forme d'une liste de 0 et 1
   éléments de la liste = reste division successive de n par 2
test si la liste est un palindrome 
   comparaison avec la liste inversée

programme avec des bugs !!

In [5]:
# digit en base 2
digit=['0','1']
def base2(n):
    """conversion base 2 d'un nombre n"""
    x = n  
    while x:
      digits=[]
      digits.append(digit[x%2])
      x = x // 2
    return digit

def TestPalindrome2(n):
    """test si la representation de n en base 2 est un palindrome"""
    L=base2(n)
    tmp=L
    L.reverse
    if (L == tmp) :
        return True
    else :
        return False
# test
res=TestPalindrome2(9)
print("pour n=9  1001  palindrome vraie:",res)
res=TestPalindrome2(12)
print("pour n=12 1100  palindrome faux :",res)
pour n=9  1001  palindrome vraie: True
pour n=12 1100  palindrome faux : True

instrumentation du programme

utilisation de print en utilisant une méthode de dichotomie pour rechercher les bogues

In [6]:
# digit en base 2
digit=['0','1']
def base2(n):
    """conversion base 2 d'un nombre n"""
    x = n  
    while x:
      digits=[]
      digits.append(digit[x%2])
      x = x // 2
    print(n,digits)
    return digit

def TestPalindrome2(n):
    """test si la representation de n en base 2 est un palindrome"""
    L=base2(n)
    #print L
    tmp=L
    tmp.reverse
    #print tmp
    if (L == tmp) :
        return True
    else :
        return False
# test
res=TestPalindrome2(9)
print("pour n=9  1001  palindrome vraie:",res)
res=TestPalindrome2(12)
print("pour n=12 1100  palindrome faux :",res)
9 ['1']
pour n=9  1001  palindrome vraie: True
12 ['1']
pour n=12 1100  palindrome faux : True

programme correcte

In [7]:
# digit en base 2
digit=['0','1']
def base2(n):
    """conversion base 2 d'un nombre n"""
    x = n
    digits=[]
    while x:
      digits.append(digit[x%2])
      x = x // 2
    digits.reverse()
    return digits

def TestPalindrome2(n):
    """test si la representation de n en base 2 est un palindrome"""
    L=base2(n)
    tmp=L[:]
    L.reverse()
    if (L == tmp) :
        return True
    else :
        return False
# test
res=TestPalindrome2(9)
print("pour n=9  1001  palindrome vraie:",res)
res=TestPalindrome2(12)
print("pour n=12 1100  palindrome faux :",res)
pour n=9  1001  palindrome vraie: True
pour n=12 1100  palindrome faux : False

Utilisation de assert

L’instruction assert permet de vérifier si une condition cdt est vérifiée. Dans le cas contraire, génère une exception et affiche le message optionnel.

syntaxe

   assert cdt [, message ]
In [8]:
x=1
assert x>0,"x doit etre positif"
assert x<0,"x doit etre negatif"
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-8-025a817daa31> in <module>()
      1 x=1
      2 assert x>0,"x doit etre positif"
----> 3 assert x<0,"x doit etre negatif"

AssertionError: x doit etre negatif

exemple d’utilisation

test si l’argument d’une fonction est valide

In [9]:
from numpy import *

def F(x):
    assert x>0, "x doit etre >0"
    return log(x)/x
# test
print(F(1))
print(F(0))
0.0
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-9-925a00bbef87> in <module>()
      6 # test
      7 print(F(1))
----> 8 print(F(0))

<ipython-input-9-925a00bbef87> in F(x)
      2 
      3 def F(x):
----> 4     assert x>0, "x doit etre >0"
      5     return log(x)/x
      6 # test

AssertionError: x doit etre >0

test si une entrée est valide

In [10]:
print("test")
x=float(input("entree un reel  #0: x="))
assert x!=0, "x doit etre non nul"
print("inverse ",1./x)
test
entree un reel  #0: x=0
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-10-3fd3c58b39a5> in <module>()
      1 print("test")
      2 x=float(input("entree un reel  #0: x="))
----> 3 assert x!=0, "x doit etre non nul"
      4 print("inverse ",1./x)

AssertionError: x doit etre non nul

FIN

In [ ]: