My problem is like this: I need to change how a function behave, but I can't access or change the file with which the function is located. I could import it though, and I would like to change the implementation a bit. However, since I can't access the source code itself, I can't change it directly. I want to actually change the function implementation so that all other files that import it will also have the new function. I'm currently trying to manipulate the code bytes of the function's __code__.co_code attribute (I know this is very bad software practice, but I really have no choice.). The __code__.co_code returns a series of bytes characters, which is very incomprehensible and extremely hard to change (I mean, like, how am I going to write a code using bytes??). I would like to inject a new code object into the function. Is there any way to first convert a Python string containing the new implementation to a series of byte characters and then inject it safely into the old function?
For a minimal reproducible example, suppose I have the following function:
def func1():
return 1
and I want to change it to:
def func1():
return 0
I've managed to access the byte code sequences of the function's __code__.co_code attribute, like this:
def func1():
return 1
code_obj = func1.__code__.co_code
print(code_obj) # prints b'd\x01S\x00'
new_code = b'd\x01S\x00' # copied the original code bytes sequence. How am I going to write `return 0` in bytes?
func1.__code__.co_code = new_code
print(func1)
code_obj2 = func1.__code__.co_code
And it gives me this error:
Traceback (most recent call last):
File "C:\Program Files\JetBrains\PyCharm 2024.1\plugins\python\helpers\pydev\pydevconsole.py", line 364, in runcode
coro = func()
File "<input>", line 7, in <module>
AttributeError: readonly attribute
It tells me that I cannot change the __code__.co_code attribute of the function. Additionally, I really don't know how to write the new function implementation (return 0) in bytes sequences. I know that I can probably make use of ASTs but I don't know how to use them either. Can anyone help me? I'm really stuck here. (Side note: I can't just shadow the old function with a new implementation because I want other files that import the library to also have the change. Also, I don't want to set the function in the module using import lib; lib.old_function = new_function.)
__code__, and that would be marginally easier: just write a new function, take its__code__and assign.def your_func(...): ...andfunc1.__code__ = your_func.__code__.__code__object instead of just monkeypatching (which you said you do not want to do)?