15

As described here, in python it is possible to replace a current module implementation using sys.modules:

import somemodule

import sys
del sys.modules['somemodule']
sys.modules['somemodule'] = __import__('somefakemodule')

But it doesn't work if import somemodule is done in the code of another imported module:

enter image description here

In this example:

CustomModule

import somemodule

def f():
    print(somemodule.someFunction())

ClientCode

from CustomModule import f

import sys
del sys.modules['somemodule']
sys.modules['somemodule'] = __import__('somefakemodule')    

f() #Will use `somemodule.someFunction`

The call to f will use somemodule.someFunction, not somefakemodule.someFunction

Is it possible to make CustomModule replace its use of somemodule for somefakemodule without changing its code? That is, from ClientCode.

Community
  • 1
  • 1

2 Answers2

18

Replace somemodule with somefakemodule before importing CustomModule:

import sys
del sys.modules['somemodule']
sys.modules['somemodule'] = __import__('somefakemodule')    

from CustomModule import f

That way, when CustomModule executes

import somemodule

Python will find somemodule in sys.modules and return the cached module, somefakemodule.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
1

A slightly better approach showing how to replace sqlite3 with pysqlite3:

if importlib.util.find_spec('pysqlite3') is not None:
    __import__('pysqlite3')
    sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
    print('Using pysqlite3 instead of sqlite3')
Shital Shah
  • 63,284
  • 17
  • 238
  • 185