如何让Python中exec/eval执行的语句像REPL顶层一样自动打印结果?
如何让exec/eval执行的代码像REPL一样自动打印结果
这个问题问到点子上了!平时用Python REPL的时候,敲个表达式就能自动看到结果,确实很方便,但换成exec、eval这类方式执行代码时,就没这个自动打印的待遇了。不过别担心,咱们完全可以手动实现类似REPL的自动打印效果,下面给你几种实用的方案:
方案1:解析AST,复刻REPL的判断逻辑
Python的REPL之所以能自动打印结果,核心是它会逐行检查执行的内容:如果是表达式语句(比如x、1+2这种没有赋值、定义操作的代码),就会执行并打印其返回值。我们可以用ast模块解析代码,手动复刻这个逻辑:
import ast def repl_exec(code, globals=None, locals=None): # 初始化全局/局部命名空间 if globals is None: globals = {} if locals is None: locals = globals # 解析代码为抽象语法树(AST) tree = ast.parse(code) for stmt in tree.body: if isinstance(stmt, ast.Expr): # 处理表达式语句:执行后打印结果 expr_code = compile(ast.Expression(stmt.value), '<repl_exec>', 'eval') result = eval(expr_code, globals, locals) print(result) # 还可以像REPL一样把结果存在下划线变量里 locals['_'] = result else: # 处理普通语句(赋值、def、class等):直接执行 stmt_code = compile(ast.Module([stmt]), '<repl_exec>', 'exec') exec(stmt_code, globals, locals)
用法示例
repl_exec(""" x = 1 + 2 x x * 3 """)
执行后会输出:
3 9
完全和REPL里的表现一致,甚至还支持_变量获取上一次的结果。
方案2:用内置code模块直接复用REPL逻辑
Python标准库的code模块提供了InteractiveConsole类,它就是原生REPL的底层实现。我们可以直接用它来执行代码,自动获得REPL的所有特性(包括自动打印结果):
import code def run_like_repl(code, globals=None, locals=None): # 创建交互式控制台实例 console = code.InteractiveConsole(globals=globals, locals=locals) # 推送代码执行,支持多行输入 console.push(code)
用法示例
run_like_repl(""" y = 10 y / 2 """)
执行后会输出:
5.0
这个方案的好处是完全复用了原生REPL的逻辑,不需要自己处理AST,还支持REPL的其他特性(比如错误提示、下划线变量)。
方案3:针对单个表达式的简化包装
如果你只是用eval执行单个表达式,可以写一个简单的包装函数,执行后自动打印结果:
def my_eval(expr, globals=None, locals=None): result = eval(expr, globals, locals) print(result) return result
用法示例
my_eval("3 ** 4")
输出:
81
这个方案适合只处理单个表达式的场景,简单直接。
原理补充
再啰嗦两句:REPL的自动打印并不是什么黑魔法,它的核心流程是:
- 读取用户输入的代码行
- 解析为AST,判断是否是表达式语句
- 如果是,执行并打印结果;如果是其他语句,直接执行
- 重复上述流程
而exec是执行语句块,不会返回任何结果;eval是执行单个表达式并返回结果,但不会主动打印。所以我们的实现本质上就是把REPL的这个判断逻辑抽出来,放到自定义的执行函数里。
内容的提问来源于stack exchange,提问作者Kevin Ushey
相关产品推荐
相关产品推荐

