sorin
sorin

Reputation: 170658

How can I create a python module that returns another module

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

Answers (1)

wim
wim

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

Related Questions