Monkey patching a class in another module in Python Monkey patching a class in another module in Python python python

Monkey patching a class in another module in Python


The following should work:

import thirdpartymodule_aimport thirdpartymodule_bdef new_init(self):    self.a = 43thirdpartymodule_a.SomeClass.__init__ = new_initthirdpartymodule_b.dosomething()

If you want the new init to call the old init replace the new_init() definition with the following:

old_init = thirdpartymodule_a.SomeClass.__init__def new_init(self, *k, **kw):    old_init(self, *k, **kw)    self.a = 43


Use mock library.

import thirdpartymodule_aimport thirdpartymodule_bimport mockdef new_init(self):    self.a = 43with mock.patch.object(thirdpartymodule_a.SomeClass, '__init__', new_init):    thirdpartymodule_b.dosomething() # -> print 43thirdpartymodule_b.dosomething() # -> print 42

or

import thirdpartymodule_bimport mockdef new_init(self):    self.a = 43with mock.patch('thirdpartymodule_a.SomeClass.__init__', new_init):    thirdpartymodule_b.dosomething()thirdpartymodule_b.dosomething()


One another possible approach, very similar to Andrew Clark's one, is to use wrapt library.Among other useful things, this library provides wrap_function_wrapper and patch_function_wrapper helpers. They can be used like this:

import wraptimport thirdpartymodule_aimport thirdpartymodule_b@wrapt.patch_function_wrapper(thirdpartymodule_a.SomeClass, '__init__')def new_init(wrapped, instance, args, kwargs):    # here, wrapped is the original __init__,    # instance is `self` instance (it is not true for classmethods though),    # args and kwargs are tuple and dict respectively.    # first call original init    wrapped(*args, **kwargs)  # note it is already bound to the instance    # and now do our changes    instance.a = 43thirdpartymodule_b.do_something()

Or sometimes you may want to use wrap_function_wrapper which is not a decorator but othrewise works the same way:

def new_init(wrapped, instance, args, kwargs):    pass  # ...wrapt.wrap_function_wrapper(thirdpartymodule_a.SomeClass, '__init__', new_init)