Sisyphe
Sisyphe

Reputation: 73

Python: How to import package twice?

Is there a way to import a package twice in the same python session, under the same name, but at different scope, in a multi-threaded environment ?

I would like to import the package, then override some of its functions to change its behavior only when used in specific class.

For instance, is it possible to achieve something like this ?

import mod

class MyClass:

  mod = __import__('mod')

  def __init__():
     mod.function = new_function # override module function

  def method():
     mod.function() # call new_function

mod.function() # call original function

It might seem weird, but in this case the user deriving the class wouldn't have to change his code to use the improved package.

Upvotes: 4

Views: 467

Answers (2)

Pynchia
Pynchia

Reputation: 11590

It looks like a job for a context manager

import modul

def newfunc():
    print('newfunc')

class MyClass:
    def __enter__(self):
        self._f = modul.func
        modul.func = newfunc
        return self

    def __exit__(self, type, value, tb):
        modul.func = self._f

    def method(self):
        modul.func()


modul.func()
with MyClass() as obj:
    obj.method()
    modul.func()
modul.func()

outputs

func
newfunc
newfunc
func

where modul.py contains

def func():
    print('func')

NOTE: this solution suits single-threaded applications only (unspecified in the OP)

Upvotes: 1

Huazuo Gao
Huazuo Gao

Reputation: 1733

To import a module as a copy:

def freshimport(name):
    import sys, importlib
    if name in sys.modules:
        del sys.modules[name]
    mod = importlib.import_module(name)
    sys.modules[name] = mod
    return mod

Test:

import mymodule as m1
m2 = freshimport('mymodule')
assert m1.func is not m2.func

Note:

importlib.reload will not do the job, as it always "thoughtfully" updates the old module:

import importlib
import mymodule as m1
print(id(m1.func))
m2 = importlib.reload(m1)
print(id(m1.func))
print(id(m2.func))

Sample output:

139681606300944
139681606050680
139681606050680

Upvotes: 2

Related Questions