我的异常是在第一个异常处理程序之后自动引发自身,但是在第二个异常处理程序完成后却无法再次引发自身。
这是一系列研究问题的一部分,在这些研究问题中,使用更具体的新问题来为更普遍的旧问题提供答案:
此示例演示了异常如何在被处理后自动引发,但第二次未能引发:
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()
我的期望是,异常应该在每个被处理的异常处理程序块的末尾自动引发,但是代码当前只执行一次。
此问题不是How to re-raise an exception in nested try/except blocks?的重复,因为该问题不涵盖在退出末尾没有明确的raise
语句的异常处理程序块时自动引发自身的异常。