Search code examples
pythonmonkeypatching

python monkey patch a new class and import it


I want to monkey patch a new class and then import that class but I get an error ModuleNotFoundError. At the same time I can use the new patched function. I believe that I miss how to add it in the "init" file.

See the following simplified example:

import numpy
class wrong_functions():
    def wrong_add(num1, num2):
        return num1 + num2 + 1

numpy.random.wrong_functions = wrong_functions
numpy.random.wrong_functions.wrong_add(1,1) # works
from numpy.random.wrong_functions import wrong_add # does not work
from numpy.random.wrong_functions import * # does not work

What do you think? Is that possible?


Solution

  • This is because of the import system.

    Reading through the doc, you can find this paragraph:

    [...] the statement from spam.ham import eggs, sausage as saus results in

    _temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], 0)
    eggs = _temp.eggs
    saus = _temp.sausage
    

    The problem is: what does __import__() does?

    The import statement combines two operations; it searches for the named module, then it binds the results of that search to a name in the local scope. [...]

    A direct call to __import__() performs only the module search and, if found, the module creation operation.

    So, when you re-import the module, your customization will be lost.

    To ensure it stays on, you can import numpy as np and then, when using np - after you assing this new class - you can always access wrong_add.

    >>> import numpy as np
    >>> np.random.wrong_functions = wrong_functions
    >>> np.random.wrong_function.wrong_add(1, 1)
    3
    

    EDIT: If you need/want to just call wrong_add instead of full package path to function, you can always assign it to a variable.

    >>> wrong_add = np.random.wrong_function.wrong_add
    >>> wrong_add(2, 2)
    5