Détection d'erreurs
Problème
On suppose qu'on souhaite réaliser une fonction en Python qui analyse un programme Python afin de dire si le programme va renvoyer une erreur.
Cette fonction nommée detection(nom_fichier) analysera le contenu d'un programme, et renverra True si le programme contient un erreur et False sinon.
On souhaite que ce problème soit décidable.
Définition : Problème de décision
Un problème de décision est dit décidable s'il existe un algorithme qui se termine en un nombre fini d'étapes, qui le décide, c'est-à-dire qui réponde par oui ou non à la question posée par le problème.
Remarque : Un programme en paramètre ?
Un programme en Python est une chaîne de caractères. Notre fonction detection aura donc la possibilité de lire le contenu de ce programme, et de l'analyser en tant que chaîne de caractères.
C'est la même chose que la commande python dans un terminal. En donnant le nom d'un fichier, le programme va être analysé par Python avant d'être exécuté.
Exemple : Un exemple d'utilisation
Soit le programme suivant :
# mon_programme.pyk = 5
while k > 0:
k = k - 1
print(1/k)
L'exécution de ce programme provoquera une erreur due à la division par zéro : ZeroDivisionError: division by zero
Donc, on s'attend à ce que la fonction detection("mon_programme.py") renvoie True.
Détecteur naïf
Si on cherche à reproduire le résultat ci-dessus, on peut facilement imaginer que la fonction detection() exécute le programme et analyse son résultat. Cela donne la fonction suivante :
def detection_naif(nom_fichier):
fichier = open(nom_fichier)
programme = fichier.read()
try:exec(programme)
return False # Pas d'erreurs !
except:return True # Une erreur est détectée
Ainsi, si le programme lève une exception, la fonction renvoie True. Sinon, la fonction renvoie False.
Malheureusement, cette fonction ne répond pas à la question posée. En effet, si on teste notre fonction avec le programme ci-dessous :
# etrange.pywhile True:
print("Hey")
alors l'appel à detection_naif("etrange.py") ne renvoie rien. Or, comme indiqué plus haut, le problème doit être décidable (ce n'est pas le cas avec cet exemple).
Détecteur parfait
Supposons désormais qu'on possède une fonction detection_parfaite() qui fonctionne parfaitement comme escompté. Montrons que ce n'est pas possible à l'aide d'un programme contre-exemple :
# echec.pyif detection_parfaite("echec.py"):
print("Et bah non, y a pas d'erreurs !")
else:print("Perdu ! Il y a une erreur")
print(1 / 0)
Voici les deux cas possibles :
Soit le programme
echec.pycontient une erreur.La fonction
detection_parfaite("echec.py")renvoieTrue.Le programme s'exécute sans erreur.
=> IMPOSSIBLE
Soit le programme
echec.pyne contient pas d'erreur.La fonction
detection_parfaite("echec.py")renvoieFalse.Le programme s'exécute avec erreur.
=> IMPOSSIBLE
Donc, par preuve par l'absurde, la fonction detection_parfaite() n'existe pas.
Donc, on vient de prouver que le problème de detection d'erreur est indécidable.