您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python:使用自定义sys.excepthook在异常发生之前在上下文中的行号处恢复程序

Python:使用自定义sys.excepthook在异常发生之前在上下文中的行号处恢复程序

进行此类任意跳转的唯一方法是在cpython中,并且以的名称 sys.settrace

这是一个来自幽goto愚人节模块的方法,它使我可以跳到(似乎)任意行:

import sys
import inspect

_line_number = None
_frame = None
def jump_to(line_number, frame):
    global _line_number, _frame
    print("Set jump to line", line_number, "in", inspect.getfile(frame))

    _frame = frame
    _line_number = line_number


def _trace(frame, event, arg):
    global _line_number, _frame

    try:
        if _line_number is not None:
            if inspect.getfile(_frame) == inspect.getfile(frame):
                print("Jumping to line", _line_number, "in", inspect.getfile(frame))
                frame.f_lineno = _line_number
                _line_number = None

    except ValueError as e:
        print(e)

    return _trace

def install():
    sys.settrace(_trace)
    frame = sys._getframe().f_back
    while frame:
        frame.f_trace = _trace
        frame = frame.f_back

如果我这样运行:

import traceh
traceh.install()

import inspect

traceh.jump_to(10, inspect.currentframe())
print(1)
print(2)
print(3)
print(4)
print(5)
print(6)

我得到令人兴奋的输出

Set jump to line 10 in tr.py
Jumping to line 10 in tr.py
4
5
6

现在,可以sys.excepthook肯定地将其嵌入吗?

...
def new_sys_excepthook(type, value, traceback):
    if type == NameError:
        jump_to(traceback.tb_lineno, traceback.tb_frame)
        traceback.tb_frame
        return

    sys.__excepthook__(type, value, traceback)


def install():
    sys.excepthook = new_sys_excepthook

    sys.settrace(_trace)
    ...

并使用它:

import traceh
traceh.install()

raise NameError
print(5)
print(6)

输出

Set jump to line 4 in tr.py

问题很明显:一旦调用sys.excepthook,外部作用域就消失了,因此绝对没有_trace机会在原始文件中运行!

如果我们 假设解决方案,然后再使用jump_to片刻,该怎么办?

import traceh
traceh.install()

import inspect

try:
    raise NameError
    print(1)
    print(2)
    print(3)
    print(4)
    print(5)
    print(6)

except:
    traceh.jump_to(10, inspect.currentframe())

这可以避免我们上次遇到的问题,因为我们正在jump_to文件内部手动调用。让我们来看看:

Set jump to line 10 in tr.py
Jumping to line 10 in tr.py
can't jump into the middle of a block

该死的

Richie Hindle将想法功劳归功于该goto模块

python 2022/1/1 18:30:42 有471人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶