Reputation: 170658
I am trying to make python module which when imported behaves exactly like another module.
python>
import foo
import fake_foo
help(foo) == help(fake_foo)
I need this because I need to add some extra code mafic code inside my fake_foo
module which dynamically loads the real module from another location.
In case it was not clear the code below does not not work for obvious reasons: load_source does return the module, but it cannot tell python to load it to current module.
# fake_foo/__init__.py
import imp
imp.load_source('foo', '/path/to/foo')
One very important requirement is that I cannot control how people are importing fake_foo
, I cannot modify the code doing the import, I need to do the whole implementation inside the fake module.
PS. I will need code that would work with py27, py35+ which is high likely that would need different logic but once I got it working for one version is shoud not be too hard to find similar ways for other versions.
Upvotes: 3
Views: 275
Reputation: 363253
It's actually trivial. Just replace in sys.modules
.
In shim module:
# mod1.py
import sys
import mod2
sys.modules["mod1"] = mod2
In real module:
# mod2.py
var = 'hello'
Demo:
>>> import mod1
>>> mod1
<module 'mod2' from 'mod2.py'>
>>> mod1.var
'potato'
That may seem hacky, but it's a feature in Python - the import machinery is intentionally allowing such a trick.
This works because the import machinery is actively enabling this hack, and as its final step pulls the actual module out of
sys.modules
, after loading it. (This is no accident. The hack was proposed long ago and we decided we liked enough to support it in the import machinery.)
From GvR: https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
Upvotes: 5