为什么在第二个异常处理程序之后没有自动再次引发异常?

时间:2019-05-15 13:37:03

标签: python python-3.x exception

我的异常是在第一个异常处理程序之后自动引发自身,但是在第二个异常处理程序完成后却无法再次引发自身。

这是一系列研究问题的一部分,在这些研究问题中,使用更具体的新问题来为更普遍的旧问题提供答案:

此示例演示了异常如何在被处理后自动引发,但第二次未能引发:

import _thread
import ctypes
import dis
import inspect
import sys

PyThreadState_SetAsyncExc = ctypes.pythonapi.PyThreadState_SetAsyncExc
# noinspection SpellCheckingInspection
PyThreadState_SetAsyncExc.argtypes = ctypes.c_ulong, ctypes.py_object
PyThreadState_SetAsyncExc.restype = ctypes.c_int


def main():
    # noinspection PyPep8,PyBroadException
    try:
        try:
            raise SpecialError
        except SpecialError as error:
            print(f'{error!r} was caught!')
            # error.reset()
    except:
        print('Exception was caught again!')
    print('You should not see this!')


class SpecialError(BaseException):
    DEBUG = False
    THROW = {dis.opmap['END_FINALLY'], dis.opmap['POP_EXCEPT']}

    def __init__(self, *args):
        super().__init__(*args)
        self.__stack = []
        self.__patch_trace()

    def __patch_trace(self):
        self.reset()
        frame = inspect.currentframe()
        while frame:
            self.__stack.append((frame, frame.f_trace))
            frame.f_trace = self.__trace
            frame = frame.f_back
        self.__stack.append(sys.gettrace())
        sys.settrace(self.__trace)

    # noinspection PyUnusedLocal
    def __trace(self, frame, event, arg):
        frame.f_trace_lines = False
        frame.f_trace_opcodes = True
        # noinspection SpellCheckingInspection
        if event == 'opcode':
            op = frame.f_code.co_code[frame.f_lasti]
            if self.DEBUG:
                print(dis.opname[op])
            if op in self.THROW:
                args = self.args

                class StateInfo(type(self)):
                    def __init__(self):
                        super().__init__(*args)

                PyThreadState_SetAsyncExc(_thread.get_ident(), StateInfo)
        return self.__trace

    def reset(self):
        if self.__stack:
            sys.settrace(self.__stack.pop())
            while self.__stack:
                frame, trace = self.__stack.pop()
                frame.f_trace = trace


if __name__ == '__main__':
    main()

我的期望是,异常应该在每个被处理的异常处理程序块的末尾自动引发,但是代码当前只执行一次。

  1. 需要做些什么才能获得例外以继续提高自己的水平?
  2. 是否有一种方法可以使异常实例检测到它被引发(可能多次),而不是仅仅被创建和初始化?

此问题不是How to re-raise an exception in nested try/except blocks?的重复,因为该问题不涵盖在退出末尾没有明确的raise语句的异常处理程序块时自动引发自身的异常。

0 个答案:

没有答案