如何解析字符串形式Python代码并判断指定变量是否被使用
问题描述
现有存储为字符串格式的Python代码片段,内容如下:
code = ''' I = 1 II = 2 print(II) '''
需要实现功能:判断代码字符串里的指定变量是否存在实际被使用的场景。
最初的实现思路是用正则匹配,代码如下:
import re def was_used(varname, codestr): used = re.findall(varname, codestr) return len(used) >= 2 print(was_used('I', code))
这个方案存在明显bug:当不同变量名存在包含关系时(比如示例中的I和II)会出现误判。上述代码执行后会错误返回True,但实际上变量I只做了定义,从未被调用使用。
实现方案
正则修正版
原正则的核心问题是没有做单词边界匹配,只要字符串里出现对应字符序列就算命中,II中包含的I字符子串会被错误统计。
修正时需要做两点处理:
- 给匹配规则加单词边界符
\b,只匹配独立出现的完整变量名,排除子串包含的误判 - 排除赋值语句左侧的变量定义场景,这部分不算变量使用
修正后的代码:
import re def was_used(varname, codestr): # 匹配变量赋值定义的场景 assign_reg = re.compile(rf'^\s*{re.escape(varname)}\s*=', re.MULTILINE) # 匹配所有独立出现的目标变量名 var_reg = re.compile(rf'\b{re.escape(varname)}\b') total_count = len(var_reg.findall(codestr)) define_count = len(assign_reg.findall(codestr)) # 总出现次数减去定义次数,剩余的就是实际使用次数 return (total_count - define_count) > 0 # 测试用例 print(was_used('I', code)) # 输出False,符合预期 print(was_used('II', code)) # 输出True,符合预期
代码里用
re.escape处理变量名,是为了避免变量名包含正则特殊字符时匹配失效。
语法树解析版(最严谨)
正则匹配始终存在覆盖不到的边界场景,比如变量名出现在注释、字符串字面量里,或者变量作为函数被定义等场景容易误判。最稳妥的方案是用Python内置的ast模块直接解析代码语法树,精准识别变量的使用场景:
import ast def was_used(varname, codestr): syntax_tree = ast.parse(codestr) for node in ast.walk(syntax_tree): # 只匹配作为加载上下文出现的变量名(即实际调用/引用,排除赋值定义) if isinstance(node, ast.Name) and node.id == varname and isinstance(node.ctx, ast.Load): return True return False # 测试用例 print(was_used('I', code)) # 输出False print(was_used('II', code)) # 输出True
这个方案完全遵循Python语法规则,不会出现正则匹配的各类边界误差。
内容的提问来源于stack exchange,提问作者user16282401
相关产品推荐
相关产品推荐

