2

Let's say I have some simple python function in a module

def f(x):
    print(x)

This function just prints its argument. However, I want to modify this function or class method, depending on what it actually is.

I have a second function:

def g(x):
    x.append(1)

which manipulates the input argument (probably a list) and appends some item. Now, I want to inject a call to g into f so that the latter would behave as

def f_patched(x):
    g(x)
    print(x)

Clearly, this can be done by monkey patching f. This however is not always practical, especially if f is some larger function as I would have to copy large portions of code (if this is even legal) just to change a single line. By injecting a call tog given some reference, for example "after line XXX" or "after instruction XXX" I could easily modify the behavior of f.

Is there a way to inject a function call into a different function? You can assume, that I know the source of f or at least that f is known well enough and unchanging for this to be possible.

4
  • 1
    You can probably splice in bytecode or something, but I'm confused as to why you want this. Commented Mar 8, 2021 at 17:59
  • Why don't you just define and use a function like f_patched? Commented Mar 8, 2021 at 18:02
  • "By injecting a call tog given some reference, for example "after line XXX" or "after instruction XXX" I could easily modify the behavior of f." There is no practical way of doing that. Commented Mar 8, 2021 at 18:02
  • To give some context: There is some function in matplotlib that could have easily been a lot more customizable with just a few extra lines of code... Commented Mar 8, 2021 at 18:03

1 Answer 1

1

Perhaps you could redefine the function early in the program (i.e. before it is first called) to replace it with your patched version:

import myModule

# before this f() is the original

old_f = myModule.f           # capture a reference to the original
def f_patched(x):
    g(x)                     # inject your code
    return old_f(x)          # use the original
myModule.f = f_patched       # replace the original

# from here onward, f() will be the patched version that calls the original
Sign up to request clarification or add additional context in comments.

5 Comments

This is precisely the monkey-patching the OP was referring to, though
Indeed, I guess I kinda aped the question. I meant to illustrate that there is no need to "copy large portions of code" though.
Yes, well,but it seems the OP doesn't just want to do something this simple, they want "By injecting a call tog given some reference, for example "after line XXX" or "after instruction XXX" I could easily modify the behavior of f."
This works if and only if the code needs to be injected before everything else that f does.
Agreed, before or after but anything within the original code would require perfect knowledge of that code and no ulterior (breaking) modification. At which point, rewriting may be safer in most cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.