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

Python中能否向函数传递表达式并捕获其文本?自定义测试工具开发需求问询

在Python中捕获函数参数的表达式文本

这绝对是可行的!Python的inspect模块配合AST(抽象语法树)工具,就能完美实现你想要的功能——捕获传递给check函数的表达式文本,不用手动重复写字符串。

核心思路

当调用check()时,我们可以:

  1. 获取调用者的栈帧,定位到调用check的源代码行;
  2. 解析该行的AST,提取出第三个参数对应的表达式文本;
  3. 结合计算出的实际值、预期值,生成你需要的输出格式。

完整实现代码

import inspect
import ast

def check(description, expected, actual_expr):
    # 先计算表达式的实际值
    actual = actual_expr
    
    # 获取调用者的栈帧(必须记得最后删除引用,避免内存泄漏)
    caller_frame = inspect.currentframe().f_back
    try:
        # 获取调用者的源代码行
        source_lines, starting_line = inspect.getsourcelines(caller_frame)
        # 找到调用check的那一行(处理行号偏移)
        call_line_idx = caller_frame.f_lineno - starting_line
        call_line = source_lines[call_line_idx].strip()
        
        # 解析该行的AST,定位到check函数的调用
        tree = ast.parse(call_line)
        expr_str = "<无法解析表达式>"
        for node in ast.walk(tree):
            if (isinstance(node, ast.Call) 
                and hasattr(node.func, 'id') 
                and node.func.id == 'check'):
                # 提取第三个参数的表达式文本
                expr_str = ast.get_source_segment(call_line, node.args[2])
                break
    finally:
        # 强制删除帧引用,防止内存泄漏
        del caller_frame
    
    # 生成结果输出
    if actual == expected:
        status = "passed"
    else:
        status = "failed"
    print(f"{description} {status}... expected: {expected} evaluated: {expr_str} got: {actual}")

# 测试用例
def call_something():
    return 10

def call_something_else():
    return 12

a = 0
check("check the total matches", 123, a + call_something() * call_something_else())

代码说明

  • 栈帧获取:inspect.currentframe().f_back拿到调用check的上下文帧,通过这个帧我们能获取到调用位置的源代码。
  • AST解析:用ast.parse把调用行的代码转为抽象语法树,然后遍历找到check的调用节点,再用ast.get_source_segment提取第三个参数的原始表达式文本——这比字符串切割更可靠,能正确处理复杂的表达式(比如带括号、嵌套函数调用的情况)。
  • 内存泄漏预防:必须手动删除栈帧引用,因为Python的垃圾回收不会自动回收栈帧对象,不删除会导致内存泄漏。

注意事项

  1. 源代码可访问性:这个方法需要能访问到调用代码的源代码文件,如果代码是从字符串动态执行的、或者是编译后的.pyc文件,可能无法获取到源代码。
  2. 多行调用处理:如果check的调用被拆分成多行(比如参数换行),需要修改代码把多行拼接成完整的调用语句后再解析。
  3. Python版本兼容:ast.get_source_segment是Python 3.8及以上版本才有的API,如果是旧版本,可以用节点的lineno和col_offset属性手动从源代码中截取表达式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 22:27:34