Existe-t-il un moyen standard d'utiliser des chaînes d'exceptions en Python? Comme l'exception Java 'causée par'?
Voici quelques informations.
J'ai un module avec une classe d'exception principale DSError
:
class DSError(Exception):
pass
Quelque part dans ce module, il y aura:
try:
v = my_dict[k]
something(v)
except KeyError as e:
raise DSError("no key %s found for %s" % (k, self))
except ValueError as e:
raise DSError("Bad Value %s found for %s" % (v, self))
except DSError as e:
raise DSError("%s raised in %s" % (e, self))
Fondamentalement, cet extrait ne devrait renvoyer que DSError et me dire ce qui s'est passé et pourquoi. Le fait est que le bloc try peut générer de nombreuses autres exceptions, donc je préférerais que je puisse faire quelque chose comme:
try:
v = my_dict[k]
something(v)
except Exception as e:
raise DSError(self, v, e) # Exception chained...
Est-ce que c'est une méthode Pythonique standard? Je n'ai pas vu de chaînes d'exceptions dans d'autres modules, comment cela se fait-il en Python?
chaînage d'exception est uniquement disponible en Python 3, où vous pouvez écrire:
try:
v = {}['a']
except KeyError as e:
raise ValueError('failed') from e
qui donne une sortie comme
Traceback (most recent call last):
File "t.py", line 2, in <module>
v = {}['a']
KeyError: 'a'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "t.py", line 4, in <module>
raise ValueError('failed') from e
ValueError: failed
Dans la plupart des cas, vous n'avez même pas besoin du from
; Python 3 affichera par défaut toutes les exceptions qui se sont produites pendant la gestion des exceptions, comme ceci:
Traceback (most recent call last):
File "t.py", line 2, in <module>
v = {}['a']
KeyError: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "t.py", line 4, in <module>
raise ValueError('failed')
ValueError: failed
Ce que vous pouvez faire dans Python 2 consiste à ajouter des attributs personnalisés à votre classe d'exception, comme:
class MyError(Exception):
def __init__(self, message, cause):
super(MyError, self).__init__(message + u', caused by ' + repr(cause))
self.cause = cause
try:
v = {}['a']
except KeyError as e:
raise MyError('failed', e)
C'est bien ce que vous demandez?
class MyError(Exception):
def __init__(self, other):
super(MyError, self).__init__(other.message)
>>> try:
... 1/0
... except Exception, e:
... raise MyError(e)
Traceback (most recent call last):
File "<pyshell#27>", line 4, in <module>
raise MyError(e)
MyError: division by zero
Si vous souhaitez stocker l'objet d'exception d'origine, vous pouvez certainement le faire dans le __init__
De votre propre classe d'exception. Vous pouvez en fait vouloir stocker le traceback car l'objet exception lui-même ne fournit pas beaucoup d'informations utiles sur l'endroit où l'exception s'est produite:
class MyError(Exception):
def __init__(self, other):
self.traceback = sys.exc_info()
super(MyError, self).__init__(other.message)
Après cela, vous pouvez accéder à l'attribut traceback
de votre exception pour obtenir des informations sur l'exception d'origine. (Python 3 fournit déjà cela en tant qu'attribut __traceback__
D'un objet d'exception.)