如何不使用eval从JSON读取函数列表并动态添加到Python类?
不用
eval从JSON加载函数并绑定为类方法的解决方案 嘿,这个需求很实际啊——毕竟eval的安全风险实在太高了,咱们完全可以用更稳妥的方式来实现从JSON加载函数并绑定到类上。核心思路是:JSON只能存基础数据类型,所以咱们把函数的**唯一标识(比如名字或模块路径)**存在JSON里,再通过安全的方式映射回对应的函数对象。
方案1:维护一个函数注册表(最安全可控)
这种方式相当于给可加载的函数加了个“白名单”,只有你提前允许的函数才能被加载,完全规避恶意代码执行的风险。
具体步骤:
- 先定义你的目标函数和对应的注册表:
# 定义要绑定到类上的方法 def a(self): print(f"方法a被调用,当前实例:{self}") def b(self): print("方法b被调用") def c(self): print("方法c被调用") # 创建函数注册表:键是函数名,值是对应的函数对象 function_registry = { "a": a, "b": b, "c": c }
- 编写JSON配置文件(比如命名为
functions_config.json),里面只存允许加载的函数名列表:
["a", "b", "c"]
- 加载JSON并配合你的装饰器使用:
import json # 读取JSON配置 with open("functions_config.json", "r") as f: function_names = json.load(f) # 从注册表中取出对应的函数对象(过滤掉不在注册表中的名字) mylist_functions = [function_registry[name] for name in function_names if name in function_registry] # 你原有的装饰器可以直接复用 def add_functions_as_methods(functions): def decorator(Class): for function in functions: setattr(Class, function.__name__, function) return Class return decorator # 给类绑定方法 @add_functions_as_methods(mylist_functions) class myclass(abstract_base): def __init__(self,*args,**kwargs): pass
方案2:通过模块路径动态导入(适合多模块场景)
如果你的函数分散在不同的模块里,可以把函数的完整模块路径存在JSON里,用importlib安全地动态导入函数。
具体步骤:
- 编写JSON配置文件,存函数的完整路径(比如
"your_module.a"):
["my_functions.a", "my_functions.b", "my_functions.c"]
- 实现路径解析和函数加载逻辑:
import json import importlib def get_function_from_path(func_full_path): # 拆分模块名和函数名(比如把"my_functions.a"拆成"my_functions"和"a") module_name, func_name = func_full_path.rsplit(".", 1) # 导入目标模块 target_module = importlib.import_module(module_name) # 获取模块中的函数对象 return getattr(target_module, func_name) # 读取JSON配置 with open("functions_config.json", "r") as f: function_paths = json.load(f) # 生成要绑定的函数列表 mylist_functions = [get_function_from_path(path) for path in function_paths] # 后续装饰器和类的使用和你原来的代码完全一致
为啥绝对不能用eval?
要是你直接用eval解析JSON里的函数名(比如JSON存"a"然后eval("a")),一旦JSON文件被篡改(比如插入"os.system('rm -rf /')"这种恶意代码),eval会直接执行这些危险操作,简直是给系统开了个后门,风险拉满。所以一定要避开这种写法。
内容的提问来源于stack exchange,提问作者00__00__00
相关产品推荐
相关产品推荐

