Je veux enregistrer le nom de l'erreur et les détails de la trace dans une variable. Voici ma tentative.
import sys
try:
try:
print x
except Exception, ex:
raise NameError
except Exception, er:
print "0", sys.exc_info()[0]
print "1", sys.exc_info()[1]
print "2", sys.exc_info()[2]
Sortie:
0 <type 'exceptions.NameError'>
1
2 <traceback object at 0xbd5fc8>
Sortie désirée:
0 NameError
1
2 Traceback (most recent call last):
File "exception.py", line 6, in <module>
raise NameError
P.S. Je sais que cela peut être fait facilement en utilisant le module traceback, mais je veux connaître l'utilisation de l'objet sys.exc_info () [2] ici.
Voici comment je le fais:
>>> import traceback
>>> try:
... int('k')
... except:
... var = traceback.format_exc()
...
>>> print var
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'k'
Cependant, vous devriez jeter un oeil à traceback documentation , car vous y trouverez peut-être des méthodes plus appropriées, selon la manière dont vous voulez traiter votre variable par la suite ...
sys.exc_info () renvoie un Tuple avec trois valeurs (type, valeur, traceback).
Par exemple, dans le programme suivant
try:
a = 1/0
except Exception,e:
exc_Tuple = sys.exc_info()
Maintenant, si nous imprimons le tuple, les valeurs seront les suivantes.
Les détails ci-dessus peuvent également être récupérés en imprimant simplement l'exception au format chaîne.
print str(e)
Utilisez traceback.extract_stack()
si vous souhaitez un accès pratique aux noms de module et de fonction et aux numéros de ligne.
Utilisez ''.join(traceback.format_stack())
si vous voulez juste une chaîne qui ressemble à la sortie traceback.print_stack()
.
Notez que même avec ''.join()
, vous obtiendrez une chaîne multiligne, car les éléments de format_stack()
contiennent \n
. Voir la sortie ci-dessous.
N'oubliez pas de import traceback
.
Voici le résultat de traceback.extract_stack()
. Ajout du formatage pour plus de lisibilité.
>>> traceback.extract_stack()
[
('<string>', 1, '<module>', None),
('C:\\Python\\lib\\idlelib\\run.py', 126, 'main', 'ret = method(*args, **kwargs)'),
('C:\\Python\\lib\\idlelib\\run.py', 353, 'runcode', 'exec(code, self.locals)'),
('<pyshell#1>', 1, '<module>', None)
]
Voici le résultat de ''.join(traceback.format_stack())
. Ajout du formatage pour plus de lisibilité.
>>> ''.join(traceback.format_stack())
' File "<string>", line 1, in <module>\n
File "C:\\Python\\lib\\idlelib\\run.py", line 126, in main\n
ret = method(*args, **kwargs)\n
File "C:\\Python\\lib\\idlelib\\run.py", line 353, in runcode\n
exec(code, self.locals)\n File "<pyshell#2>", line 1, in <module>\n'
Faites attention lorsque vous retirez l'objet exception ou l'objet traceback du gestionnaire d'exceptions, car cela entraînerait des références circulaires et que gc.collect()
ne parviendrait pas à être collecté. Cela semble être un problème particulier dans l'environnement de bloc-notes ipython/jupyter où l'objet traceback n'est pas effacé au bon moment et même un appel explicite à gc.collect()
dans la section finally
ne fait rien. Et c’est un énorme problème si vous avez des objets énormes dont la mémoire ne récupère pas pour cette raison (par exemple, CUDA pour des exceptions de mémoire insuffisantes pour lesquelles cette solution n’a pas besoin d’un redémarrage complet du noyau pour pouvoir récupérer).
En général, si vous souhaitez enregistrer l'objet de suivi, vous devez le supprimer des références à locals()
, comme suit:
import sys, traceback, gc
type, val, tb = None, None, None
try:
myfunc()
except:
type, val, tb = sys.exc_info()
traceback.clear_frames(tb)
# some cleanup code
gc.collect()
# and then use the tb:
if tb:
raise type(val).with_traceback(tb)
Dans le cas de jupyter notebook, vous devez au moins le faire dans le gestionnaire d'exceptions:
try:
myfunc()
except:
type, val, tb = sys.exc_info()
traceback.clear_frames(tb)
raise type(val).with_traceback(tb)
finally:
# cleanup code in here
gc.collect()
Testé avec Python 3.7.
p.s. Le problème avec ipython ou jupyter notebook env, c’est qu’il dispose de la magie %tb
qui enregistre la trace et la rend disponible à tout moment ultérieurement. Et par conséquent, aucune locals()
dans toutes les images participant à la trace ne sera libérée tant que le bloc-notes n'aura pas quitté ou qu'une autre exception ne remplacera la trace précédente stockée. C'est très problématique. Il ne faut pas stocker le traçage sans nettoyer ses cadres. Fix soumis ici .
L'objet peut être utilisé comme paramètre dans la fonction Exception.with_traceback()
:
except Exception as e:
tb = sys.exc_info()
print(e.with_traceback(tb[2]))