How to automatically re-raise exception after hand

2020-02-16 03:54发布

问题:

In C#, threads have an Abort method that causes a ThreadAbortException to be raised in them wherever they might be running. Python does not have this feature, and so it has been implemented. However, this implementation does not cause the exception to be automatically re-raised once at the end of all the exception handling.

Some experiments were tried with sys.settrace and also ThreadAbortException.__del__ without success. These seem to be on the right track to implementing an exception that can automatically raise itself again. Unfortunately, a clean implementation that might also support a future ResetAbort method for threads is a bit difficult for me to figure out.

Here is the implementation that has been written so far:

#! /usr/bin/env python3
import ctypes
import threading

PyThreadState_SetAsyncExc = ctypes.pythonapi.PyThreadState_SetAsyncExc
PyThreadState_SetAsyncExc.argtypes = ctypes.c_ulong, ctypes.py_object
PyThreadState_SetAsyncExc.restype = ctypes.c_int


def set_async_exc(thread_id, exception):
    if not isinstance(thread_id, int):
        raise TypeError('thread_id should be of type int')
    if not issubclass(exception, BaseException):
        raise TypeError('exception should be subclass of BaseException')
    return PyThreadState_SetAsyncExc(thread_id, exception)


class ThreadAbortException(SystemExit):
    pass


class CThread(threading.Thread):
    def abort(self):
        set_async_exc(self.ident, ThreadAbortException)

My expectation is an instance of the ThreadAbortException should be able to automatically raise itself again sometime after it has been caught and handled. It would probably need to be raised either after the context in which it was handled is returning to a caller or when it is collected by the garbage collector. Does anyone have some idea how to accomplish this?