38

I have a problem overriding the method where from...import statement is used. Some example to illustrate the problem:

# a.py module
def print_message(msg):
    print(msg)

# b.py module
from a import print_message
def execute():
    print_message("Hello")

# c.py module which will be executed
import b
b.execute()

I'd like to override print_message(msg) method without changing code in a or b module. I tried in many ways but from...import imports the original method. When I changed the code to

import a
a.print_message

then I see my change.

Could you suggest how to solve this problem?

------------------ Update ------------------

I tried to do that like below e.g.:

# c.py module
import b
import a
import sys
def new_print_message(msg):
    print("New content")
module = sys.modules["a"]
module.print_message = new_print_message
sys.module["a"] = module

But this is not working where I'm using for...import statement. Is working only for import a but as I wrote I don't want change code in b.py and a.py modules.

Anton Menshov
  • 2,266
  • 14
  • 34
  • 55
Pawel
  • 525
  • 1
  • 5
  • 7
  • 1
    (1) What exactly do you mean by "override"? Monkey patch? (2) In the code that you present, there's only one `print_message()`. – NPE May 31 '12 at 07:33
  • I want change print_message() method to print e.g. "New content" message. How to achieve that from c.py file without change in a.py and b.py? – Pawel May 31 '12 at 07:38
  • 1
    for explanation and demonstration of "monkey patch": http://stackoverflow.com/a/6647776/1498405 – hardmooth Aug 18 '15 at 14:46

2 Answers2

62

With your a and b modules untouched you could try implementing c as follows:

import a

def _new_print_message(message):
    print "NEW:", message

a.print_message = _new_print_message

import b
b.execute()

You have to first import a, then override the function and then import b so that it would use the a module that is already imported (and changed).

uhz
  • 2,468
  • 1
  • 20
  • 20
  • 2
    Your code is working. My mistake was that I put import b statement before override print_message method. With import b after a.print_message = _new_print_message code is working. Thanks for help. – Pawel May 31 '12 at 08:00
  • PEP-8 recommends putting all import statements at the top of the module. It's the same as having an include statement in the middle of a .cpp file; you will just end up in a world of pain. – Steztric Oct 18 '17 at 10:16
  • This code works. But when I adding types to python, this method fails. I had to write `a.print_message = _new_print_message` again in the `__init__` method. Is there anyway to solve this? – Pablo LION Dec 21 '21 at 02:52
  • @Steztric Very misleading. Not all projects will work with all imports at the top since some imports are conditional. Python is not C++. – Beyondo Dec 15 '22 at 02:49
0

module1.py

def function1():
    print("module1 function1")
    function2()

def function2():
    print("module1 function2")

module2.py

import module1

test = module1.function1()
print(test) 

""" output
module1 function1
module1 function2
"""
def myfunction():
    print("module2 myfunction")

module1.function2 = lambda: myfunction()

test = module1.function1()
print(test)

"""output
module1 function1
module2 myfunction
"""