Skip to main content
 首页 » 编程设计

python之将 __builtins__ 恢复为默认值

2025年05月04日30yjmyzz

如果我编码有误并且我做了这样的事情:

__builtins__ = 'abcd' 

在我没有编写代码之前 import builtins 有没有办法将 __builtins__ 恢复到它的默认值?

请您参考如下方法:

让我们假设一个比所描述的情况更糟糕的情况:你完全毁掉、核武器、摧毁、歼灭和消灭 __builtins__:

__builtins__.__dict__.clear() 

@Matrtijn 的方法将失败,因为每个模块都将具有完全相同的 builtins 实例。


首先,我们必须恢复基本类型:

__builtins__.object = "".__class__.__mro__[-1] 
__builtins__.type = object.__class__ 

根据 python docs , __mro__ 属性:是在方法解析期间查找基类时考虑的类的元组。由于每个 python 现代类都扩展了 object,它允许我们获得 object 类型的实例。

其次,我们将实现类查找。给定一个类名,我们将返回类的类型。为此,我们将使用 type.__subclasses__()递归地(有关更多信息,请参阅 this question):

def all_subclasses_of(cls): 
    return type.__subclasses__(cls) + [g for s in type.__subclasses__(cls) for g in all_subclasses_of(s)] 
def lookup(s): 
    for cls in all_subclasses_of(object): 
        if cls.__name__ == s: 
            return cls 

第三,我们将使用 BuiltinImporter 提取已经加载的模块:

bi = lookup('BuiltinImporter') 
modules = bi.load_module.__globals__['sys'].modules 

我们利用 BuiltinImporter 导入 sys 模块这一事实,然后我们使用 sys.modules : 将模块名称映射到已加载模块的字典。

然后,我们将使用下一步所需的方法和类修补 __builtins__:

__builtins__.hasattr = lambda obj, key: key in obj.__dict__ 
__builtins__.KeyError = lookup('KeyError') 

现在,让奇迹发生吧!

bi.load_module('builtins') 
__builtins__ = bi.load_module.__globals__['module_from_spec'](modules['builtins'].__spec__) 

我们使用 builtinImporter.load_module 为 builtins 模块生成 __spec__ .然后,我们从生成的规范中加载模块。 并且有效!(我真的不知道为什么,但它确实有效)

但是,新生成的 builtins 模块缺少方法 open 和所有异常。我们必须手动添加它们才能使 import 再次工作:

__builtins__.BaseException = lookup('BaseException') 
__builtins__.open = lambda name, mode: modules['io'].FileIO(name, mode) 
for error in all_subclasses_of(BaseException): 
    __builtins__.__dict__[error.__name__] = error