处理异常后如何从上次尝试的指令继续执行帧?

Jul*_*oux 11 python

我想NameError通过将所需的缺失变量注入到帧中来处理异常,然后从上一次尝试的指令继续执行.

以下伪代码应说明我的需求.

def function():
    return missing_var

try:
    print function()

except NameError:

    frame = inspect.trace()[-1][0]

    # inject missing variable
    frame.f_globals["missing_var"] = ...

    # continue frame execution from last attempted instruction
    exec frame.f_code from frame.f_lasti
Run Code Online (Sandbox Code Playgroud)

在repl.it上阅读整个unittest

笔记

背景

代码在从属进程中运行,该进程由父进程控制.任务(真正的功能)写在父级中,后者使用dill传递给从站.我希望一些任务(在slave进程中运行)尝试从父进程中的外部作用域访问变量,我希望slave能够动态地向父进程请求这些变量.

ps:我不希望这种魔法在生产环境中运行.

Ben*_*son 4

与各种评论者所说的相反,Python 中可以进行“错误时恢复”异常处理。图书馆fuckit.py实施上述策略。它通过在导入时重写模块的源代码、在每个语句周围插入try...except块并吞掉所有异常来消除错误。那么也许你可以尝试类似的策略?

\n\n

不言而喻:那个图书馆只是一个笑话。永远不要在生产代码中使用它。

\n\n
\n\n

您提到您的用例是捕获对丢失名称的引用。您是否考虑过使用元编程在“智能”命名空间(例如 )的上下文中运行代码defaultdict?(这也许只是比 坏主意稍微好一点fuckit.py。)

\n\n
from collections import defaultdict\n\nclass NoMissingNamesMeta(type):\n    @classmethod\n    def __prepare__(meta, name, bases):\n        return defaultdict(lambda: "foo")\n\nclass MyClass(metaclass=NoMissingNamesMeta):\n    x = y + "bar"  # y doesn\'t exist\n\n>>> MyClass.x\n\'foobar\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

NoMissingNamesMeta是一个元类- 用于定制语句行为的语言构造class。在这里,我们使用该__prepare__方法来自定义字典,该字典将在创建类期间用作类的命名空间。因此,因为我们使用的是 adefaultdict而不是常规字典,所以元类为 的类NoMissingNamesMeta永远不会获得NameError. 创建类期间引用的任何名称都将自动初始化为"foo".

\n\n

这种方法类似于 @Andr\xc3\xa9Fratelli\ 的从对象手动请求延迟初始化数据的想法Scope。在生产中我会这样做,而不是这样做。元类版本需要更少的输入来编写客户端代码,但代价是更多的魔法。(想象一下你自己在两年内调试这段代码,试图理解为什么不存在的变量被动态地引入作用域!)

\n