Reputation: 31171
I'm trying to write some code that is robust against __import__
being changed, because the Pydev debugger overrides __import__.
So, I need a way of accessing the built-in __import__
function.
>>> 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?
There are questions on SO about recovering removed built-ins but in this case the global has been replaced.
Upvotes: 1
Views: 912
Reputation: 40713
This is a somewhat tricky issue as python will not be interested in reloading the __builtin__
module as it hasn't changed. You will be forced to delete the __builtin__
module so as to force python to reimport it. You can also bypass __import__
by using importlib
(only true in python3, in python2 importlib
resorts to __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
Upvotes: 1
Reputation: 31171
Whilst I haven't found a way of recovering __import__
itself, using ihooks
I can get a function that acts as __import__
does:
import ihooks
ihooks.ModuleImporter().install()
# or
works_just_like__import__ = ihooks.ModuleImporter().import_module
Upvotes: 0
Reputation: 122052
Looking at the code you link, the original builtins.__import__
is passed to the new ImportHookManager
instance and stored as the _system_import
attribute.
Based on the answers to How to get instance given a method of the instance?, therefore, you could do something like:
__import__ = __import__.im_self._system_import
to restore the original function. Note that the leading underscore marks this attribute as private-by-convention, though, and the implementation/attribute name could be changed without warning.
Upvotes: 1