This might work for you. First, some code:
a.py
b = 42
fakery.py
class Fakery(object): def __init__(self, mod): self.module = __import__(mod) import sys sys.modules[self.module.__name__] = self def __getattr__(self, name): print "__getattr__ called with '%s'" % name result = getattr(self.module, name) if name == 'b': result += 1 return result
Example
>>> import fakery >>> fakery.Fakery('a') <fakery.Fakery object at 0x109007110> >>> from a import b __getattr__ called with '__path__' __getattr__ called with 'b' >>> print b 43 >>> import a >>> print a <fakery.Fakery object at 0x109007110>
All you have to do is change the Fakery class to do what you want to do. In this case, I just add 1 to a b .
I hope this is clear how this works, but here is a quick explanation.
When a module is imported, its entry is populated in sys.modules . When you instantiate a Fakery object, it imports the module by name (using __import__ ), and then replaces that module entry in sys.modules with itself.
Python imports modules only once, storing the imported module in sys.modules . Each import after the first returns an entry in sys.modules. The Fakery object inserts itself in sys.modules['a'] , replacing the real module. All subsequent import a or from a import <whatever> Fakery now routed to the Fakery instance. Since this is just a class, you can do all kinds of crazy things using magic methods or metaprogramming.
__getattr__ convenient because it is called when the requested attribute does not exist.
Seth
source share