获取 `exec` 调用中最后一个表达式的值

fer*_*lin 7 python python-3.x

假设我在字符串中有一些 python 代码

code = """
a = 42
a
"""
Run Code Online (Sandbox Code Playgroud)

和我exec那串代码:

result = exec(code)
Run Code Online (Sandbox Code Playgroud)

那么result永远都是None。有没有办法获得最后一个表达式的值?在这种情况下,那将是5, 因为a是最后一个表达式。

编辑:这是我询问的功能的另一个示例。假设我们有 python 代码(存储在变量中code

a = 100
sqrt(a)
Run Code Online (Sandbox Code Playgroud)

那么我怎样才能以这样的方式执行代码以给我结果10- 也就是说,sqrt(a)

编辑 编辑:另一个例子:我希望的代码exec

function_a()
function_b()
function_c()
Run Code Online (Sandbox Code Playgroud)

有什么办法可以定义某种magic_exec函数,以便

magic_exec(code)
Run Code Online (Sandbox Code Playgroud)

会为我提供价值function_c()吗?

use*_*347 5

该请求当然是有效的,因为在创建基于 Python 的环境期间我也需要这样的函数。我用以下利用 Python ast 机制的代码解决了这个问题:

def my_exec(script, globals=None, locals=None):
    '''Execute a script and return the value of the last expression'''
    stmts = list(ast.iter_child_nodes(ast.parse(script)))
    if not stmts:
        return None
    if isinstance(stmts[-1], ast.Expr):
        # the last one is an expression and we will try to return the results
        # so we first execute the previous statements
        if len(stmts) > 1:
            exec(compile(ast.Module(body=stmts[:-1]), filename="<ast>", mode="exec"), globals, locals)
        # then we eval the last one
        return eval(compile(ast.Expression(body=stmts[-1].value), filename="<ast>", mode="eval"), globals, locals)
    else:
        # otherwise we just execute the entire code
        return exec(script, globals, locals)
Run Code Online (Sandbox Code Playgroud)

代码应该是不言自明的,基本上它

  1. 将脚本分成多个语句
  2. 如果最后一个是表达式,则将第一部分作为语句执行,将最后一部分作为表达式执行。
  3. 否则将整个脚本作为语句执行。


Chr*_*sso 0

exec('a = 4')
print a % prints 4

>>> code = """
... a = 42
... b = 53"""
>>> exec(code)
>>> a
42
>>> b
53
Run Code Online (Sandbox Code Playgroud)

或者,如果你说你不知道最后一个是 b,那么你可以这样:

code = """  
a = 4
b = 12
abc_d=13
"""
t = re.findall(r'''.*?([A-Za-z0-9_]+)\s*?=.*?$''', code)
assert(len(t)==1)
print t[0] % prints 13
Run Code Online (Sandbox Code Playgroud)