Python中使用exec执行脚本后,如何移除全局函数或本地执行?
解决exec()执行脚本污染全局作用域的问题
核心思路
别直接用全局作用域globals()跑脚本,而是创建独立的局部作用域来存执行生成的函数,执行完后这个局部作用域会被自动回收,不会留下残留。
推荐方案:使用自定义局部作用域
修改你的执行器函数,给exec()传入自定义的局部字典,脚本里定义的函数只会存在于这个局部字典中,完全不会污染全局。
修改后的代码:
def execute(body: ExecutorCommand): try: # 创建独立的局部作用域字典 local_scope = {} # 执行脚本,将函数/变量存入局部作用域 exec(body.script, globals(), local_scope) # 从局部作用域中取出handler函数 demo_handler = local_scope.get("demo_handler") if not callable(demo_handler): return {"success": False, "error": {"type": "MissingHandler", "message": "脚本中未定义可调用的demo_handler函数"}} result = demo_handler(body.request) return {"success": True, "data": result} except Exception as ex: return {"success": False, "error": {"type": type(ex).__name__, "message": repr(ex)}}
这个方案的优势:
- 每次执行的脚本完全隔离,不会有残留函数影响后续请求
- 局部作用域在函数执行结束后会被Python垃圾回收机制自动清理,无需手动处理
- 不会误删全局作用域原本存在的函数或变量
备选方案:清理全局作用域(不推荐)
如果因为特殊原因必须用全局作用域,可以在执行脚本前后对比全局函数,删除新增的部分。但这种方法风险高,比如脚本修改了已有的全局函数时无法处理,多线程场景下还可能出现误删。
示例代码:
def execute(body: ExecutorCommand): pre_funcs = None try: # 记录执行前全局中的可调用对象 pre_funcs = set(k for k, v in globals().items() if callable(v)) exec(body.script, globals()) demo_handler = globals().get("demo_handler") if not callable(demo_handler): return {"success": False, "error": {"type": "MissingHandler", "message": "脚本中未定义可调用的demo_handler函数"}} result = demo_handler(body.request) return {"success": True, "data": result} except Exception as ex: return {"success": False, "error": {"type": type(ex).__name__, "message": repr(ex)}} finally: # 无论成功失败都清理新增的函数 if pre_funcs is not None: post_funcs = set(k for k, v in globals().items() if callable(v)) for func_name in post_funcs - pre_funcs: del globals()[func_name]
内容的提问来源于stack exchange,提问作者Sha
相关产品推荐
相关产品推荐

