如果我编码有误并且我做了这样的事情:
__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
关于python - 将 __builtins__ 恢复为默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25824010/