覆盖后可以恢复__import__吗?

时间:2015-02-19 13:31:06

标签: python python-2.7 built-in

我正在尝试编写一些针对__import__被修改的强大代码,因为the Pydev debugger overrides __import__

因此,我需要一种访问内置__import__函数的方法。

>>> def fake_import(*args, **kwargs): pass # some other implementation here
... 
>>> import __builtin__
>>> __builtin__.__import__ = fake_import
# can I recover the original value of __import__ here?

有关recovering removed built-ins的问题,但在这种情况下,全球已被替换。

3 个答案:

答案 0 :(得分:1)

查看您链接的代码,原始builtins.__import__将传递到新的ImportHookManager实例,并存储为_system_import属性。

因此,基于How to get instance given a method of the instance?的答案,您可以执行以下操作:

__import__ = __import__.im_self._system_import

恢复原始功能。请注意,前导下划线将此属性标记为按惯例私有,并且可以在不发出警告的情况下更改实现/属性名称。

答案 1 :(得分:1)

这是一个棘手的问题,因为python不会对重新加载__builtin__模块感兴趣,因为它没有改变。您将被迫删除__builtin__模块,以强制python重新导入它。您也可以使用__import__绕过importlib(仅在python3中为true,在python2 importlib中指向__import__)。

import sys
import importlib

import __builtin__ as old_builtins

class ExampleImporter(object):
    old_import = __import__
    def __init__(self):
       self.count = 0
    def new_import(self, *args, **kwargs):
        self.count += 1
        print(args, kwargs)
        return self.old_import(*args, **kwargs)
importer = ExampleImporter()

old_builtins.__import__ = importer.new_import
assert __import__ == importer.new_import

# remove builtins from modules so as to force its reimport
del sys.modules["__builtin__"]
# in python3 the following bypasses __import__ entirely, but not in python2
new_builtins = importlib.import_module("__builtin__") 
# restore initial state of __builtin__ module (will not delete new names 
# added to __builtin__)
old_builtins.__dict__.update(new_builtins.__dict__)
# Replace new __builtin__ with old __builtin__ module. Otherwise you'll end up with a 
# mess where different modules have different a __builtin__ module.
sys.modules["__builtin__"] = old_builtins
del new_builtins

assert __import__ == importer.old_import
assert importer.count == 1 # would be 0 in python3

答案 2 :(得分:0)

虽然我还没有找到恢复__import__本身的方法,但使用ihooks我可以获得一个充当__import__的函数:

import ihooks
ihooks.ModuleImporter().install()

# or
works_just_like__import__ = ihooks.ModuleImporter().import_module