Python:使用自定义sys.excepthook在异常之前在上下文中的行号处恢复程序
目标是在下面的代码中解析Python:使用自定义sys.excepthook在异常之前在上下文中的行号处恢复程序,python,Python,目标是在下面的代码中解析os依赖关系,并执行ls命令 我想知道如何用双星来做我在下面评论中提到的事情 我已经知道我可以通过回溯 也就是说,我想知道在给定的上下文中,是否有可能在给定的行号上恢复程序的执行 import sys def new_sys_excepthook(type, value, traceback): if type == NameError: pass # Resolution of the exception finding the
os
依赖关系,并执行ls
命令
我想知道如何用双星来做我在下面评论中提到的事情
我已经知道我可以通过回溯
也就是说,我想知道在给定的上下文中,是否有可能在给定的行号上恢复程序的执行
import sys
def new_sys_excepthook(type, value, traceback):
if type == NameError:
pass
# Resolution of the exception finding the module dependency and doing the import
# ** Returning to the line that created the exception with the right
# ** context and continue the execution with the module
# ** dependency resolved
# call original excepthook if we can't solve the issue
sys.__excepthook__(type, value, traceback)
sys.excepthook = new_sys_excepthook
system("ls")
执行此类任意跳转的唯一方法是在CPython中,是一个名为
sys.settrace
的实现细节
这里有一个方法,取自幽默的愚人节模块,它让我跳转到(似乎)任意的行:
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,外部作用域就消失了,因此,\u trace
没有机会在原始文件中运行
如果我们假设它有一个解决方案,然后再使用跳转到一会儿,会怎么样
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\u以
。让我们看看:
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的创意功劳很大。我知道您必须使用自定义excepthook而不是简单的try except块,是吗?是的,因为最终目标是创建一个库(这将覆盖全局异常挂钩)当异常发生时,自动执行\uuuu导入\uuuu
。这里的真正意图是什么?一种不知道stdlib的人可以使用的DSL?更好的方法是使用一个神奇的全局dict来执行代码,它相应地定义了\uuu getitem\uuu
。仍然是一个黑客,但要少一些丑陋和侵扰。你能详细介绍一下神奇的全球格言吗?这样做的目的是在有一个选择的情况下动态地进行模块导入(这不是一个严肃的项目,只是开玩笑看看什么是可行的)。原始上下文不再存在,异常已在顶层捕获,现在将发生的是解释器将退出。