Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Gestion d'erreurs dans python

36 réponses
Avatar
ian
Bonjour,

Ayant donne la chance a python (contre l'avis de la direction... :p) il
s'avere que j'ai eu raison ... Nous avons d'excellents resultats en terme de
dev, de vitesse (c'etait la principale crainte) et il tient ses promesses:
on peut utiliser le meme code sur PC X86 comme sur le materiel embedded,
qu'il soit en SH3 ou en ARM ... La classe! :)

Maintenant, une question : la gestion des erreurs. Quand ca plante quelque
part, il indique l'erreur etcetc, le module qui a plante ne tourne plus,
mais le reste si, ce qui donne une impression que le soft tourne toujours
mais avec une partie en moins.. Pas pratique.
Je me suis dit qu'il devait y avoir un parametre a passer a python pour
qu'il sorte (ou relance) automatiquement a la moindre erreur, stype
python -onerrorrestart xxx.pyc, vous voyez le genre .. et la, dans la doc,
horreur, je trouve rien...

Donc, comme il est impossible de tout prevoir, et que je ne peux pas mettre
de try catch partout, existe-t-il un moyen de dire a python de fermer ou
relancer le soft des qu'une erreur (grave ou non) apparait ?

Merci

10 réponses

1 2 3 4
Avatar
Thomas Paviot
Bonjour,

Ayant donne la chance a python (contre l'avis de la direction... :p) il
s'avere que j'ai eu raison ... Nous avons d'excellents resultats en terme de
dev, de vitesse (c'etait la principale crainte) et il tient ses promesses:
on peut utiliser le meme code sur PC X86 comme sur le materiel embedded,
qu'il soit en SH3 ou en ARM ... La classe! :)

Maintenant, une question : la gestion des erreurs. Quand ca plante quelque
part, il indique l'erreur etcetc, le module qui a plante ne tourne plus,
mais le reste si, ce qui donne une impression que le soft tourne toujours
mais avec une partie en moins.. Pas pratique.
Je me suis dit qu'il devait y avoir un parametre a passer a python pour
qu'il sorte (ou relance) automatiquement a la moindre erreur, stype
python -onerrorrestart xxx.pyc, vous voyez le genre .. et la, dans la doc,
horreur, je trouve rien...

Donc, comme il est impossible de tout prevoir, et que je ne peux pas mettre
de try catch partout, existe-t-il un moyen de dire a python de fermer ou
relancer le soft des qu'une erreur (grave ou non) apparait ?

Merci




Bonjour,

J'ai été confronté au problème que tu évoques : lorsque l'on 'freeze' un
script python avec py2exe, un exception qui se produit dans le script ne
provoque pas l'arrêt du programme : la sortie sdterr est simplement
redirigée vers un fichier texte, auquel on peut avoir accès une fois le
thread terminé. J'ai donc dû trouver une méthode demandant explicitement
d'arrêter le programme si une exception est levée ( à l'aide de sys.exit())

J'ai créé le module Error.py suivant:

############ Error.py
import sys

def _exceptionhook(type, value, traceb):
print >>sys.stderr,type
print >>sys.stderr,value
print >>sys.stderr," at line :",traceb.tb_lineno
sys.exit()

sys.excepthook = _exceptionhook
############

J'enregistre la sortie stderr dans un fichier que j'envoie par mail au
moment du sys.exit() . Cette fonction d'envoi de mail (SendBugReport)est
enregistrée à l'aide de atexit() au moment où une exception se produit.
Voici donc la fin du script:

############# Suite de Error.py
class RedirectErr:
#
# Redirige la sortie stderr pour envoyer l'erreur par mail
#
def __init__(self,stderr):
self.stderr=stderr
self.content=""
self.error_occuredúlse
self.file_error=None

def write(self,text):
if not self.error_occured:
#
# Première erreur
# D'abord on enregistre la fonction atexit
import atexit
atexit.register(SendBugReport)
# puis on ouvre le fichier qui contient les erreurs
self.file_error=open("Erreur.txt",'w')
self.error_occured=True
if self.file_error is not None:
self.file_error.write(text)
self.file_error.flush()

sys.stderr=RedirectErr(sys.stderr)
##################

Ce module demande certainement à être amélioré mais il satisfait très
bien mon besoin.

En espérant t'avoir aidé,

Cordialement,

Thomas Paviot

Avatar
PEYROUX
On 9 mar, 06:30, Thomas Paviot wrote:



Bonjour,

Ayant donne la chance a python (contre l'avis de la direction... :p) il
s'avere que j'ai eu raison ... Nous avons d'excellents resultats en ter me de
dev, de vitesse (c'etait la principale crainte) et il tient ses promess es:
on peut utiliser le meme code sur PC X86 comme sur le materiel embedded,
qu'il soit en SH3 ou en ARM ... La classe! :)

Maintenant, une question : la gestion des erreurs. Quand ca plante quel que
part, il indique l'erreur etcetc, le module qui a plante ne tourne plus,
mais le reste si, ce qui donne une impression que le soft tourne toujou rs
mais avec une partie en moins.. Pas pratique.
Je me suis dit qu'il devait y avoir un parametre a passer a python pour
qu'il sorte (ou relance) automatiquement a la moindre erreur, stype
python -onerrorrestart xxx.pyc, vous voyez le genre .. et la, dans la d oc,
horreur, je trouve rien...

Donc, comme il est impossible de tout prevoir, et que je ne peux pas me ttre
de try catch partout, existe-t-il un moyen de dire a python de fermer ou
relancer le soft des qu'une erreur (grave ou non) apparait ?

Merci


Bonjour,

J'ai été confronté au problème que tu évoques : lorsque l'on 'f reeze' un
script python avec py2exe, un exception qui se produit dans le script ne
provoque pas l'arrêt du programme : la sortie sdterr est simplement
redirigée vers un fichier texte, auquel on peut avoir accès une fois le
thread terminé. J'ai donc dû trouver une méthode demandant explicit ement
d'arrêter le programme si une exception est levée ( à l'aide de sys .exit())

J'ai créé le module Error.py suivant:

############ Error.py
import sys

def _exceptionhook(type, value, traceb):
print >>sys.stderr,type
print >>sys.stderr,value
print >>sys.stderr," at line :",traceb.tb_lineno
sys.exit()

sys.excepthook = _exceptionhook
############

J'enregistre la sortie stderr dans un fichier que j'envoie par mail au
moment du sys.exit() . Cette fonction d'envoi de mail (SendBugReport)est
enregistrée à l'aide de atexit() au moment où une exception se prod uit.
Voici donc la fin du script:

############# Suite de Error.py
class RedirectErr:
#
# Redirige la sortie stderr pour envoyer l'erreur par mail
#
def __init__(self,stderr):
self.stderr=stderr
self.content=""
self.error_occuredúlse
self.file_error=None

def write(self,text):
if not self.error_occured:
#
# Première erreur
# D'abord on enregistre la fonction atexit
import atexit
atexit.register(SendBugReport)
# puis on ouvre le fichier qui contient les erreurs
self.file_error=open("Erreur.txt",'w')
self.error_occured=True
if self.file_error is not None:
self.file_error.write(text)
self.file_error.flush()

sys.stderr=RedirectErr(sys.stderr)
##################

Ce module demande certainement à être amélioré mais il satisfait très
bien mon besoin.

En espérant t'avoir aidé,

Cordialement,

Thomas Paviot


Et pourquoi pas déclencher une exception SystemExit.
Exemple :

try :
a = connection()
except Exception, ex :
print ex
raise SystemExit


Avatar
BertrandB

Evidemment si j'ai pas le choix jvais try catcher tout ca, mais bon



Perso je trouve la multiplication des blocs try catch fatigant, alors
que j'apprécie le mode Perl qui incite jsutement à faire un test et à
documenter chaque retour de fonction.

JeFaisQuelqueChose() or die "ca n'a pas marché"

Je pense que l'on peut mimer ce même style avec Python.

Avatar
Laurent Pointal

Evidemment si j'ai pas le choix jvais try catcher tout ca, mais bon



Perso je trouve la multiplication des blocs try catch fatigant, alors
que j'apprécie le mode Perl qui incite jsutement à faire un test et à
documenter chaque retour de fonction.


Je préfère les exceptions... si on a oublié l'incitation, l'erreur
remonte toute seule, avec tout plein d'informations associées (ça manque
un peu dans les status). Et si on veut cacher l'erreur, il faut la
traiter explicitement dans un bloc try/except.

JeFaisQuelqueChose() or die "ca n'a pas marché"

Je pense que l'on peut mimer ce même style avec Python.


Tant que le JeFaisQuelqueChose() ne lève pas d'exception, mais se
contente de retourner un booléen ou code d'erreur, il suffit de définir
une fonction die() et ça devrais faire pareil.
Mais c'est pas du tout dans l'esprit de Python (ie. la pluspart des
erreurs sont retournées sous forme d'exception, pour passer en xxx() or
die() il faut intercepter toutes les exceptions dans xxx()).

Laurent.


Avatar
ian
Bonjour,

Superbe idee que j'ai immediatement teste et adopte, une gestion globale des
exceptions c'etait inespere, je peux la traiter (log, mail ..) et fermer le
programme ensuite ! Merci beaucoup !!! :)

(j'ai bien fait de repasser voir la discussion :p)


Bonjour,

J'ai été confronté au problème que tu évoques : lorsque l'on 'freeze' un
script python avec py2exe, un exception qui se produit dans le script ne
provoque pas l'arrêt du programme : la sortie sdterr est simplement
redirigée vers un fichier texte, auquel on peut avoir accès une fois le
thread terminé. J'ai donc dû trouver une méthode demandant explicitement
d'arrêter le programme si une exception est levée ( à l'aide de
sys.exit())


J'ai créé le module Error.py suivant:

############ Error.py
import sys

def _exceptionhook(type, value, traceb):
print >>sys.stderr,type
print >>sys.stderr,value
print >>sys.stderr," at line :",traceb.tb_lineno
sys.exit()

sys.excepthook = _exceptionhook
############

J'enregistre la sortie stderr dans un fichier que j'envoie par mail au
moment du sys.exit() . Cette fonction d'envoi de mail (SendBugReport)est
enregistrée à l'aide de atexit() au moment où une exception se produit.
Voici donc la fin du script:

############# Suite de Error.py
class RedirectErr:
#
# Redirige la sortie stderr pour envoyer l'erreur par mail
#
def __init__(self,stderr):
self.stderr=stderr
self.content=""
self.error_occuredúlse
self.file_error=None

def write(self,text):
if not self.error_occured:
#
# Première erreur
# D'abord on enregistre la fonction atexit
import atexit
atexit.register(SendBugReport)
# puis on ouvre le fichier qui contient les erreurs
self.file_error=open("Erreur.txt",'w')
self.error_occured=True
if self.file_error is not None:
self.file_error.write(text)
self.file_error.flush()

sys.stderr=RedirectErr(sys.stderr)
##################

Ce module demande certainement à être amélioré mais il satisfait très
bien mon besoin.

En espérant t'avoir aidé,

Cordialement,

Thomas Paviot



Avatar
Bertrand B

Tant que le JeFaisQuelqueChose() ne lève pas d'exception, mais se
contente de retourner un booléen ou code d'erreur, il suffit de déf inir
une fonction die() et ça devrais faire pareil.
Yes mais on perd le bénéfice des exception


Mais c'est pas du tout dans l'esprit de Python (ie. la pluspart des
erreurs sont retournées sous forme d'exception, pour passer en xxx() or
die() il faut intercepter toutes les exceptions dans xxx()).

Laurent.


La lourdeur des blocs try fait qu'on en général les programmeur laiss ent
remonter les exceptions au lieu de traiter celles-ci au plus près. La
fiabilité des programmes s'en ressent. La méthode à la perl amène
finalement à une meilleur fiabilité puisque le programmeur doit pense r à
traiter ou commenter précisément chaque cas d'anomalie.
On pourrait imaginer des mécanisme plus sophistiqué et plus sympa du
style d'une méthode de la classe fonction qui serait chargé de captur er
les exceptions émises dans la fonction. Ou un bloc exception en fin des
blocs de définitions de fonctions. Bon je ne vais pas PEPer plus haut
que mon cul plus longtemps ;-)

Avatar
Laurent Pointal

Tant que le JeFaisQuelqueChose() ne lève pas d'exception, mais se
contente de retourner un booléen ou code d'erreur, il suffit de définir
une fonction die() et ça devrais faire pareil.
Yes mais on perd le bénéfice des exception


Mais c'est pas du tout dans l'esprit de Python (ie. la pluspart des
erreurs sont retournées sous forme d'exception, pour passer en xxx() or
die() il faut intercepter toutes les exceptions dans xxx()).

Laurent.


La lourdeur des blocs try fait qu'on en général les programmeur laissent
remonter les exceptions au lieu de traiter celles-ci au plus près. La
fiabilité des programmes s'en ressent.


Je trouve try/except moins lourd que le traitement au cas par cas - les
gouts et les couleurs...

Et comme ça, quand les exceptions remontent, c'est qu'il n'y a pas de
traitement d'erreur à faire (ou que le développeur a écrit du code
jetable sans traitement d'erreur).
Mais en tout cas elles ne sont pas passées sous silence (ce qui a des
effets indésirables à postériori nettement plus difficiles à cerner).
C'est pour cette raison qu'on conseill de ne jamais mettre en place de
filtre except "catchall" de façon inconsidérée.

La méthode à la perl amène
finalement à une meilleur fiabilité puisque le programmeur doit penser à
traiter ou commenter précisément chaque cas d'anomalie.


Là, je ne suis pas d'accord. J'ai fait pas mal de C (en plus du C++), où
il faut gérer les erreurs de cette façon [*]. Sauf à avoir des
développeurs très expérimentés et qui blindent leur code - rare - on
retrouve généralement des codes de retour non traités...

Si les exceptions ont été inventées, c'est bien parce que les contrôles
de retours de fonctions n'est pas la panacée - mais dans certains
langages, y'a pas le choix (et on s'y fait).

On pourrait imaginer des mécanisme plus sophistiqué et plus sympa du
style d'une méthode de la classe fonction qui serait chargé de capturer
les exceptions émises dans la fonction. Ou un bloc exception en fin des
blocs de définitions de fonctions. Bon je ne vais pas PEPer plus haut
que mon cul plus longtemps ;-)


Ben, tu ajoutes un décorateur à ta fonction, avec un bloc try/except
autour de l'appel à la fonction et zoooo.

A+

Laurent.

[*] On peut utiliser des macros + setjmp/longjmp... mais ça n'empêche
que 99,9% des librairies fonctionnent par retour de code de
réussite/erreur qu'il faut tester au cas par cas (avec des logiques
variant d'une lib à une autre, bien entendu).


Avatar
Bruno Desthuilliers

Tant que le JeFaisQuelqueChose() ne lève pas d'exception, mais se
contente de retourner un booléen ou code d'erreur, il suffit de définir
une fonction die() et ça devrais faire pareil.
Yes mais on perd le bénéfice des exception


Mais c'est pas du tout dans l'esprit de Python (ie. la pluspart des
erreurs sont retournées sous forme d'exception, pour passer en xxx() or
die() il faut intercepter toutes les exceptions dans xxx()).

Laurent.


La lourdeur des blocs try


Pardon ? Tu a déjà essayé d'avoir une gestion d'erreur fiable et non
intrusive avec un langage n'ayant pas de support pour les exceptions ?

Franchement, plus light (et plus souple) que les exceptions, je ne
connais pas.

fait qu'on en général les programmeur laissent
remonter les exceptions au lieu de traiter celles-ci au plus près.


Qui a dit qu'il fallait les gérer "au plus près" ? Le bon endroit pour
gérer une exception, c'est là où on a le contexte nécessaire pour la
gérer - ce qui est très différent de "au plus près".


La
fiabilité des programmes s'en ressent.


En quoi ?

La méthode à la perl amène
finalement à une meilleur fiabilité puisque le programmeur doit penser à
traiter ou commenter précisément chaque cas d'anomalie.


Mdr.

gestion d'erreur à la Perl:
fait_quelquechose ou crashe("ça n'a pas marché")

C'est du Garcimore, ta gestion d'erreur. Le résultat final est
exactement le même que celui d'une exception non gérée (traceback en
moins). C'est toi qui parles de "fiabilité" ?


On pourrait imaginer des mécanisme plus sophistiqué et plus sympa du
style d'une méthode de la classe fonction qui serait chargé de capturer
les exceptions émises dans la fonction.


Pour quoi faire ? Ce n'est pas parce qu'une fonction lève une exception
qu'il faut rattraper cette exception à ce niveau là (si tu sais gérer
l'exception au niveau de la fonction, tu ne la laisse pas se propager,
donc si tu la laisse se propager c'est que ce n'est précisément pas le
bon endroit pour la gérer, cqfd). Au contraire, le principe est de
laisser à toute la pile d'appel (que la fonction ne connait pas *et n'a
pas à connaitre*) la possibilité de décider si elle veut gérer cette
exception ou non. Le tout sans avoir à tester des codes d'erreur, mettre
des conditionnelles dans tous les sens et se repasser le même paquet
d'informations de fonction en fonction.

Ou un bloc exception en fin des
blocs de définitions de fonctions.


OOh, oui, génial. Comme les 'on error go to...' de VB ?

Bon je ne vais pas PEPer plus haut
que mon cul plus longtemps ;-)



Avatar
ian
Re,

Un bemol cependant : le hook ne marche pas si l'exception se produit dans un
thread :(

+++
Avatar
Bertrand B


Pardon ? Tu a déjà essayé d'avoir une gestion d'erreur fiable et non
intrusive avec un langage n'ayant pas de support pour les exceptions ?

Je n'ai pas dit ça enfin ;)


Qui a dit qu'il fallait les gérer "au plus près" ? Le bon endroit p our
gérer une exception, c'est là où on a le contexte nécessaire po ur la
gérer - ce qui est très différent de "au plus près".



On m'aurait donc menti ?
plus sérieusement il y a un peu trop de modules qui laissent remonter
des exceptions sans les traiter.
Je n'ai pas la prétention d'être un king de la programmation n'y d'av oir
les bonnes habitudes.
Par contre celle de poser toutes les questions y compris les plus c....


La méthode à la perl amène finalement à une meilleur fiabilité puisque
le programmeur doit penser à traiter ou commenter précisément ch aque
cas d'anomalie.


Mdr.

C'est déjà ça

gestion d'erreur à la Perl:
fait_quelquechose ou crashe("ça n'a pas marché")

pas faux


Pour quoi faire ? Ce n'est pas parce qu'une fonction lève une excepti on
qu'il faut rattraper cette exception à ce niveau là (si tu sais gé rer
l'exception au niveau de la fonction, tu ne la laisse pas se propager,
donc si tu la laisse se propager c'est que ce n'est précisément pas le
bon endroit pour la gérer, cqfd).


A condition de ne pas la laisser remonter par simple fainéantise.

Ok par contre la personne qui créé un module est la plus à même à
comprendre ce qui peut générer les exceptions ? Et d'y remédier ?


Ou un bloc exception en fin des blocs de définitions de fonctions.


OOh, oui, génial. Comme les 'on error go to...' de VB ?



Ouii pourquoi pas (bien que le on error goto est un débranchement des
plus sauvages et génère un joyeux bordel dans les sources.
PS: c'est quoi VB ? j'en suis resté à Sbasic ....


--

Bon je ne vais pas PEPer plus haut que mon cul plus longtemps ;-)


1 2 3 4