如何在Python反汇编器中访问栈内容并提取调用的函数与方法
解决方案
用AST语法树替代字节码栈模拟(更简便可靠)
直接用Python标准库的ast模块分析代码,比手动模拟反汇编栈要直观得多,还能避开栈操作逻辑的复杂坑:
- 遍历AST节点,定位
Call类型节点:所有函数/方法调用都会对应这个节点 - 识别实例方法调用:如果
Call的func属性是Attribute类型,那就是类似ls.append的实例方法——value字段对应实例名,attr字段对应方法名 - 自动过滤列表推导式内部调用:AST里的
ListComp节点会单独处理推导逻辑,不会把<listcomp>当成普通函数调用,不用额外做过滤判断
示例代码片段:
import ast def extract_calls(node): calls = [] if isinstance(node, ast.Call): # 处理函数/方法调用 if isinstance(node.func, ast.Attribute): # 实例方法调用,比如 obj.method obj_name = node.func.value.id if isinstance(node.func.value, ast.Name) else "<unknown>" method_name = node.func.attr calls.append(f"{obj_name}.{method_name}") elif isinstance(node.func, ast.Name): # 普通函数调用 calls.append(node.func.id) # 递归遍历所有子节点 for child in ast.iter_child_nodes(node): calls.extend(extract_calls(child)) return calls # 测试示例 code = """ def test2(): [x for x in range(10)] ls = [] ls.append(1) """ tree = ast.parse(code) print(extract_calls(tree)) # 输出: ['range', 'ls.append']
若坚持用字节码反汇编,完善栈逻辑的要点
如果必须基于字节码栈模拟,得针对性解决问题:
- 过滤特殊内部调用:遇到
<listcomp>、<genexpr>这类语法糖生成的内部函数名,直接跳过记录 - 严格对齐字节码栈规范:对照Python官方的字节码指令说明,精准模拟每个指令的栈操作——比如
LOAD_ATTR会把栈顶对象替换为对应属性值,CALL_METHOD要根据参数数量正确弹出栈元素 - 增加边界检查:对栈操作加判断,比如弹出元素前先确认栈不为空,避免崩溃
栈控制的参考资料
- Python官方文档的「字节码指令集」章节,详细说明了每个指令的栈行为
- CPython源码里的
Python/ceval.c文件,是字节码解释器的核心实现,能看到栈操作的具体逻辑
内容的提问来源于stack exchange,提问作者mathfux
相关产品推荐
相关产品推荐

