使用 Python AST 确定字符串是否已硬编码到打印调用中

BBr*_*lyn 0 python abstract-syntax-tree

我正在尝试编写一个函数,该函数将使用 AST 来确定某个字符串是否已被硬编码到打印函数调用中。例如,如果这是整个 Python 文件:

print("hard coded")
Run Code Online (Sandbox Code Playgroud)

我得到的树如下:

with open(filename, 'r') as f:
    tree = ast.parse(f.read())

nodes = [node for node in ast.walk(tree)]
Run Code Online (Sandbox Code Playgroud)

现在nodes包含[<_ast.Module object at 0x7fa250286150>, <_ast.Expr object at 0x7fa250286050>, <_ast.Call object at 0x7fa2502642d0>, <_ast.Name object at 0x7fa228014610>, <_ast.Str object at 0x7fa228014710>, <_ast.Load object at 0x7fa2280080d0>]

通过测试 attrs 我可以发现nodes[2]有一个.func.idand nodes[2].func.id == 'print',所以这是我的打印命令。但是我如何找到传递给这个打印命令的参数呢?硬编码字符串位于ast.Str列表索引 4 处出现的对象中,但我需要专门确定该字符串已传递给打印,而不仅仅是该字符串出现在文件中。

wja*_*rea 5

对象Call有一个args可以使用的属性,例如:

for node in ast.walk(tree):
    if (
            isinstance(node, ast.Call)  # It's a call
            and isinstance(node.func, ast.Name)  # It directly invokes a name
            and node.func.id == 'print'  # That name is `print`
            ):
        # Check if any arg is the one we're looking for
        print(any(
            arg.value == "hard coded"
            for arg in node.args
            if isinstance(arg, ast.Constant)
            ))
Run Code Online (Sandbox Code Playgroud)

输出:

True
Run Code Online (Sandbox Code Playgroud)

在 Python 3.10+ 中,您可以使用结构模式匹配来简化isinstance内容:

for node in ast.walk(tree):
    match node:
        # If it's a call to `print`
        case ast.Call(func=ast.Name(id='print')):
            # Check if any arg is the one we're looking for
            for arg in node.args:
                match arg:
                    case ast.Constant(value="hard coded"):
                        print('found')
                        break
Run Code Online (Sandbox Code Playgroud)

输出:

found
Run Code Online (Sandbox Code Playgroud)