it-swarm.com.de

Erhöhen die Python-Ausnahme und die Stapelverfolgung auf

Ich versuche, eine Ausnahme in einem Thread einzufangen und sie im Haupt-Thread erneut anzuheben:

import threading
import sys

class FailingThread(threading.Thread):
    def run(self):
        try:
            raise ValueError('x')
        except ValueError:
            self.exc_info = sys.exc_info()

failingThread = FailingThread()
failingThread.start()
failingThread.join()

print failingThread.exc_info
raise failingThread.exc_info[1]

Dies funktioniert grundsätzlich und ergibt folgende Ausgabe:

(<type 'exceptions.ValueError'>, ValueError('x',), <traceback object at 0x1004cc320>)
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    raise failingThread.exc_info[1]

Die Quelle der Ausnahme verweist jedoch auf Zeile 16, in der die erneute Erhöhung aufgetreten ist. Die ursprüngliche Ausnahme stammt aus Zeile 7. Wie muss ich den main - Thread so ändern, dass die Ausgabe lautet:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
52
roskakori

In Python 2 müssen Sie alle drei Argumente verwenden, um zu erhöhen:

raise failingThread.exc_info[0], failingThread.exc_info[1], failingThread.exc_info[2]

durch Übergeben des Traceback-Objekts als drittes Argument wird der Stapel beibehalten.

Von help('raise'):

Wenn ein drittes Objekt vorhanden ist und nicht None, muss es sich um ein traceback - Objekt handeln (siehe Abschnitt Die Standardtyphierarchie ). Statt der aktuellen Position wird Ersetzt als Ort, an dem die Ausnahme aufgetreten ist. Wenn das dritte Objekt vorhanden ist und kein Traceback-Objekt oder None, wird eine TypeError-Ausnahme ausgelöst. Die - Form mit drei Ausdrücken von raise ist hilfreich, um eine Ausnahme In einer Exceptionsklausel transparent wiederzugeben, aber raise ohne Ausdrücke Sollte vorgezogen werden, wenn die Ausnahme erneut sein soll -raised war die aktuellste Ausnahmebedingung im aktuellen Bereich.

In diesem Fall können Sie keine Version ohne Ausdruck verwenden.

Für Python 3 (wie in den Kommentaren):

raise failingThread.exc_info[1].with_traceback(failingThread.exc_info[2])

oder Sie können die Ausnahmen einfach mit raise ... from ... verketten, dies löst jedoch eine verkettete Ausnahme aus, wobei der ursprüngliche Kontext im Attribut cause angehängt ist und möglicherweise nicht das ist, was Sie möchten.

51
Duncan

Dieses Code-Snippet funktioniert in Python 2 und 3:

      1 try:
----> 2     raise KeyError('Default key error message')
      3 except KeyError as e:
      4     e.args = ('Custom message when get re-raised',) #The comma is not a typo, it's there to indicate that we're replacing the Tuple that e.args pointing to with another Tuple that contain the custom message.
      5     raise
1
Steven Than

Könntest du es so schreiben:

try:
    raise ValueError('x')
except ValueError as ex:
    self.exc_info = ex

und dann die stacktrace aus der Ausnahme verwenden?

0
Ivaylo Petrov