You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Python中eval()和exec()多行代码按先进先出顺序执行?

问题:multiline_eval函数执行顺序不符合预期

我参考了Stack Overflow上的一个问题,使用了其中的multiline_eval函数,代码如下:

def multiline_eval(expr, context={}):
    """Evaluate several lines of input, returning the result of the last line"""
    tree = ast.parse(expr)
    eval_exprs = []
    exec_exprs = []
    for module in tree.body:
        if isinstance(module, ast.Expr):
            eval_exprs.append(module.value)
        else:
            exec_exprs.append(module)
    exec_expr = ast.Module(exec_exprs, type_ignores=[])
    exec(compile(exec_expr, 'file', 'exec'), context)
    results = []
    for eval_expr in eval_exprs:
        results.append(eval(compile(ast.Expression((eval_expr)), 'file', 'eval'), context))
    return '\n'.join([str(r) for r in results])

调用该函数执行以下代码时:

multiline_eval('''
print("Hello World1")

for a in range(5):
    print(a)
print("Hello World2")
''')

实际输出顺序为:

0
1
2
3
4
Hello World1
Hello World2

但期望的输出顺序是:

Hello World1
0
1
2
3
4
Hello World2

尝试修改代码未成功,请求指导如何调整代码实现预期输出顺序。


解决方案

问题出在原函数把ast.Expr类型的语句(比如直接的print()调用,属于表达式语句)和其他执行语句分开处理——先执行所有非表达式的exec语句,再单独处理表达式语句,直接打乱了代码原本的执行顺序。

要修复这个问题,核心是保留代码原本的执行顺序,不要拆分表达式和其他语句,按原顺序逐个处理每一条语句:

修改后的代码如下:

import ast

def multiline_eval(expr, context=None):
    """按顺序执行多行输入,返回所有表达式语句的结果拼接"""
    if context is None:
        context = {}
    tree = ast.parse(expr)
    results = []
    for stmt in tree.body:
        if isinstance(stmt, ast.Expr):
            # 处理表达式语句,执行并收集结果
            result = eval(compile(ast.Expression(stmt.value), 'file', 'eval'), context)
            if result is not None:
                results.append(str(result))
        else:
            # 处理执行语句,直接执行
            exec(compile(ast.Module([stmt], type_ignores=[]), 'file', 'exec'), context)
    return '\n'.join(results)

关键调整说明:

  1. 移除原函数中拆分exec_exprs和eval_exprs的逻辑,改为遍历每一条语句按原顺序处理
  2. 对每条语句判断类型后分别处理:
    • 若为ast.Expr(如print()调用这类表达式语句),用eval执行并收集结果
    • 其他语句(如for循环)直接用exec执行
  3. 修复了原代码中context默认参数的可变陷阱(用None作为默认值,函数内初始化空字典)

测试修改后的函数,执行原调用代码,即可得到预期的输出顺序:

Hello World1
0
1
2
3
4
Hello World2

内容的提问来源于stack exchange,提问作者Hunt3r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:40:28