有没有办法从代码字符串构造代码对象并将其分配给使用Python的现有函数?

问题描述 投票:0回答:1

我的问题是这样的:我需要更改函数的行为方式,但无法访问或更改该函数所在的文件。不过,我可以import

,并且我想稍微改变一下实现。但是,由于我无法访问源代码本身,因此无法直接更改它。我实际上想
更改函数实现,以便import
的所有其他文件也将具有新函数。我目前正在尝试操作函数的 
__code__.co_code
 属性的代码字节(我知道这是非常糟糕的软件实践,但我
真的别无选择。)。 __code__.co_code
返回一系列字节字符,这是非常难以理解并且极难更改的(我的意思是,我将如何使用字节编写代码??)。我想将一个新的代码对象注入到该函数中。有没有办法首先将包含新实现的Python字符串转换为一系列字节字符,然后将其安全地注入到旧函数中?

对于一个最小的可重现示例,假设我有以下函数:

def func1(): return 1
我想将其更改为:

def func1(): return 0
我已经成功访问了函数的 

__code__.co_code

 属性的字节码序列,如下所示:

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
它给了我这个错误:

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
它告诉我无法更改函数的 

__code__.co_code

 属性。此外,我
真的不知道如何以字节序列编写新函数实现(return 0
)。我知道我可能可以使用 AST,但我也不知道如何使用它们。谁能帮我?我真的被困在这里了。 (旁注:我不能只是用新的实现来隐藏旧函数,因为我希望导入库的其他文件也进行更改。另外,我不想使用 
import lib; lib.old_function = new_function
 在模块中设置函数.)

python function byte python-internals
1个回答
0
投票
你激励我闲逛了一下。

当心!我不是专家。我不知道这是否是一个坏主意,如果是坏主意,我不知道它会坏到什么程度。

#!/usr/bin/env python3 a=1 print(f"a={a}") # a=1 def func(): global a a = a+1 print("func()") # func() func() print(f"a={a}") # a=2 source_code = """ global a a = a+17 """ code_obj = compile(source_code, '<string>', 'exec') print("func.__code__ = code_obj") func.__code__ = code_obj print("func()") # func() func() print(f"a={a}") # a=19
显然,这个示例仅适用于没有参数且没有显式返回值的函数。请不要问我如何让它适用于带有参数或返回值的函数。

© www.soinside.com 2019 - 2024. All rights reserved.