__import__ 覆盖后是否可以恢复?
Is it possible to recover __import__ after overwriting it?
我正在尝试编写一些能够抵抗 __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?
SO 上有关于 recovering removed built-ins 的问题,但在这种情况下全局已被替换。
查看您 link 的代码,原始 builtins.__import__
被传递给新的 ImportHookManager
实例并存储为 _system_import
属性。
根据 How to get instance given a method of the instance? 的答案,您可以这样做:
__import__ = __import__.im_self._system_import
恢复原来的功能。请注意,前导下划线将此属性标记为按约定私有,并且 implementation/attribute 名称可以在没有警告的情况下更改。
虽然我还没有找到恢复 __import__
本身的方法,但使用 ihooks
我可以获得一个功能,就像 __import__
一样:
import ihooks
ihooks.ModuleImporter().install()
# or
works_just_like__import__ = ihooks.ModuleImporter().import_module
这是一个有点棘手的问题,因为 python 不会对重新加载 __builtin__
模块感兴趣,因为它没有改变。您将被迫删除 __builtin__
模块以强制 python 重新导入它。您还可以使用 importlib
绕过 __import__
(仅在 python3 中为真,在 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
我正在尝试编写一些能够抵抗 __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?
SO 上有关于 recovering removed built-ins 的问题,但在这种情况下全局已被替换。
查看您 link 的代码,原始 builtins.__import__
被传递给新的 ImportHookManager
实例并存储为 _system_import
属性。
根据 How to get instance given a method of the instance? 的答案,您可以这样做:
__import__ = __import__.im_self._system_import
恢复原来的功能。请注意,前导下划线将此属性标记为按约定私有,并且 implementation/attribute 名称可以在没有警告的情况下更改。
虽然我还没有找到恢复 __import__
本身的方法,但使用 ihooks
我可以获得一个功能,就像 __import__
一样:
import ihooks
ihooks.ModuleImporter().install()
# or
works_just_like__import__ = ihooks.ModuleImporter().import_module
这是一个有点棘手的问题,因为 python 不会对重新加载 __builtin__
模块感兴趣,因为它没有改变。您将被迫删除 __builtin__
模块以强制 python 重新导入它。您还可以使用 importlib
绕过 __import__
(仅在 python3 中为真,在 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