如何获取Python/Sage代码块的最后表达式结果?
实现Jupyter风格的Python运算结果缓存方案
问题场景
在Jupyter中运行Python或Sage代码时,代码块的最后一行表达式会自动返回结果(如执行
a=42;b=43;a+b会返回85);若最后一行是赋值语句则无返回。现需实现类似逻辑以缓存Python运算结果,尝试使用print(_)失败,直接给最后一行添加res=会因缩进等问题失效。
优雅实现方案
方案一:基于AST语法树的代码动态修改
通过解析代码的抽象语法树(AST),自动识别最后一行是否为表达式,再动态修改代码实现结果缓存,完美适配缩进、多行结构等复杂场景。
实现代码
import ast def execute_and_cache(code, cache_var="_last_result"): # 解析代码生成AST树 tree = ast.parse(code) if not tree.body: return None last_stmt = tree.body[-1] # 判断最后一行是否为表达式(排除赋值、函数定义、类定义等语句) if isinstance(last_stmt, ast.Expr): # 将原表达式替换为赋值语句,存入缓存变量 assign_node = ast.Assign( targets=[ast.Name(id=cache_var, ctx=ast.Store())], value=last_stmt.value ) tree.body[-1] = assign_node # 添加表达式节点,保留原表达式的返回行为 tree.body.append(ast.Expr(value=ast.Name(id=cache_var, ctx=ast.Load()))) # 编译修改后的AST并执行 compiled_code = compile(tree, filename="<cached_exec>", mode="exec") exec(compiled_code, globals()) # 返回缓存的结果 return globals().get(cache_var, None)
使用示例
# 最后一行为表达式,自动缓存结果 code_block = """ a = 42 b = 43 a + b """ result = execute_and_cache(code_block) print(result) # 输出:85 print(_last_result) # 直接访问缓存变量,输出:85 # 最后一行为赋值语句,不缓存结果 code_block2 = """ x = 100 y = x * 2 """ result2 = execute_and_cache(code_block2) print(result2) # 输出:None
方案二:自定义交互式缓存控制台
如果需要搭建类似Jupyter的交互式环境,可以继承Python内置的code.InteractiveConsole,重写输入处理逻辑实现自动缓存:
实现代码
import code import ast class CachedInteractiveConsole(code.InteractiveConsole): def push(self, line): try: # 解析单行输入的AST tree = ast.parse(line) if tree.body and isinstance(tree.body[-1], ast.Expr): # 动态添加缓存赋值语句 expr_str = ast.unparse(tree.body[-1].value) modified_line = f"{line.rstrip()}\n{self.cache_var} = {expr_str}" return super().push(modified_line) return super().push(line) except SyntaxError: # 多行输入(如函数、循环)交给父类处理 return super().push(line) # 初始化控制台,指定缓存变量名 console = CachedInteractiveConsole(locals=globals()) console.cache_var = "_last_result" console.interact("缓存式Python控制台(结果存于_last_result)")
注意事项
- Python 3.9及以上版本支持
ast.unparse,低版本可使用第三方库astor替代 - 处理多行代码时,AST会自动识别完整语句结构,无需担心缩进或嵌套逻辑冲突
- 可自定义缓存变量名,避免与用户代码中的变量命名冲突
内容的提问来源于stack exchange,提问作者tobiasBora
相关产品推荐
相关产品推荐

