使用 Python AST 确定字符串是否已被硬编码到打印调用中
Using Python AST to determine if a string has been hard-coded into a print call
我正在尝试编写一个函数,该函数将使用 AST 来确定某个字符串是否已被硬编码到打印函数调用中。例如,如果这是整个 Python 文件:
print("hard coded")
我得到的树如下:
with open(filename, 'r') as f:
tree = ast.parse(f.read())
nodes = [node for node in ast.walk(tree)]
现在 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.id
和 nodes[2].func.id == 'print'
,所以这是我的打印命令。但是我如何找到传递给这个打印命令的参数呢?硬编码字符串位于列表索引 4 处的 ast.Str
对象中,但我需要明确确定该字符串已传递给打印,而不仅仅是该字符串出现在文件中。
一个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)
))
输出:
True
在 Python 3.10+ 中,您可以使用 structural pattern matching 来简化 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
输出:
found
我正在尝试编写一个函数,该函数将使用 AST 来确定某个字符串是否已被硬编码到打印函数调用中。例如,如果这是整个 Python 文件:
print("hard coded")
我得到的树如下:
with open(filename, 'r') as f:
tree = ast.parse(f.read())
nodes = [node for node in ast.walk(tree)]
现在 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.id
和 nodes[2].func.id == 'print'
,所以这是我的打印命令。但是我如何找到传递给这个打印命令的参数呢?硬编码字符串位于列表索引 4 处的 ast.Str
对象中,但我需要明确确定该字符串已传递给打印,而不仅仅是该字符串出现在文件中。
一个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)
))
输出:
True
在 Python 3.10+ 中,您可以使用 structural pattern matching 来简化 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
输出:
found