How does one monkey patch a function in python? How does one monkey patch a function in python? python python

How does one monkey patch a function in python?


It may help to think of how Python namespaces work: they're essentially dictionaries. So when you do this:

from a_package.baz import do_something_expensivedo_something_expensive = lambda: 'Something really cheap.'

think of it like this:

do_something_expensive = a_package.baz['do_something_expensive']do_something_expensive = lambda: 'Something really cheap.'

Hopefully you can realize why this doesn't work then :-) Once you import a name into a namespace, the value of the name in the namespace you imported from is irrelevant. You're only modifying the value of do_something_expensive in the local module's namespace, or in a_package.baz's namespace, above. But because bar imports do_something_expensive directly, rather than referencing it from the module namespace, you need to write to its namespace:

import barbar.do_something_expensive = lambda: 'Something really cheap.'


There's a really elegant decorator for this: Guido van Rossum: Python-Dev list: Monkeypatching Idioms.

There's also the dectools package, which I saw an PyCon 2010, which may be able to be used in this context too, but that might actually go the other way (monkeypatching at the method declarative level... where you're not)


If you want to only patch it for your call and otherwise leave the original code you can use https://docs.python.org/3/library/unittest.mock.html#patch (since Python 3.3):

with patch('a_package.baz.do_something_expensive', new=lambda: 'Something really cheap.'):    print do_something_expensive()    # prints 'Something really cheap.'print do_something_expensive()# prints 'Something expensive!'