it-swarm.com.de

Python Verkettung von Ausnahmen

Gibt es eine Standardmethode für die Verwendung von Ausnahmeketten in Python? Wie die Java Ausnahme 'verursacht durch'?

Hier einige Hintergrundinformationen.

Ich habe ein Modul mit einer Hauptausnahmeklasse DSError:

 class DSError(Exception):
     pass

Irgendwo in diesem Modul wird es sein:

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))

Grundsätzlich sollte dieses Snippet nur DSError werfen und mir sagen, was passiert ist und warum. Die Sache ist, dass der try-Block möglicherweise viele andere Ausnahmen auslöst, daher würde ich es vorziehen, wenn ich etwas tun kann wie:

try:
    v = my_dict[k]
    something(v)
except Exception as e:
    raise DSError(self, v, e)  # Exception chained...

Ist das Standard Pythonic Weg? Ich habe keine Ausnahmeketten in anderen Modulen gesehen. Wie funktioniert das in Python?

73
Ayman

Ausnahme-Verkettung ist nur in Python 3 verfügbar, wo Sie schreiben können:

try:
    v = {}['a']
except KeyError as e:
    raise ValueError('failed') from e

was ergibt eine Ausgabe wie

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

In den meisten Fällen benötigen Sie nicht einmal das from; Python 3 zeigt standardmäßig alle Ausnahmen an, die während der Ausnahmebehandlung aufgetreten sind:

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

Was Sie in Python 2 tun können, ist das Hinzufügen von benutzerdefinierten Attributen zu Ihrer Ausnahmeklasse, wie zum Beispiel:

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)
106
phihag

Ist es das, wonach du fragst?

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

Wenn Sie das ursprüngliche Ausnahmeobjekt speichern möchten, können Sie dies natürlich in Ihrer eigenen Ausnahmeklasse __init__ Tun. Möglicherweise möchten Sie den Traceback tatsächlich speichern, da das Ausnahmeobjekt selbst nicht viele nützliche Informationen darüber enthält, wo die Ausnahme aufgetreten ist:

class MyError(Exception):
    def __init__(self, other):
        self.traceback = sys.exc_info()
        super(MyError, self).__init__(other.message)

Danach können Sie auf das Attribut traceback Ihrer Ausnahme zugreifen, um Informationen zur ursprünglichen Ausnahme abzurufen. (Python 3 stellt dies bereits als das Attribut __traceback__ Eines Ausnahmeobjekts bereit.)

5
BrenBarn