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

如何批量从多个.py文件中提取Python字节码并解决dis输出捕获问题

Python批量提取.py文件字节码解决方案

方法说明

你不需要手动把.py文件的代码包裹到def中,直接编译源码或者动态导入模块,就能提取到文件内所有定义的函数、类方法甚至顶层代码的字节码。核心思路是:

  • 遍历目标目录下所有.py文件
  • 直接编译每个py文件得到模块级代码对象
  • 递归遍历代码对象的co_consts属性,提取所有函数/类的代码对象
  • 用dis.dis()输出字节码到指定文件

你现有代码的错误点

  • py_compile.main()传入的是不带路径的文件名,无法定位到源文件,需要传入完整的文件绝对路径
  • 遍历pyc文件时glob.glob('*.pyc')默认读取当前工作目录的pyc,你的pyc存放在__pycache__目录下,路径不匹配
  • 打开pyc文件用了r文本模式,pyc是二进制文件,必须用rb模式打开
  • 变量名混乱:代码中出现未定义的f3、file变量,上下文没有声明
  • 写入文件逻辑错误:不能直接把StringIO对象写入文件,需要调用out.getvalue()获取字节码字符串再写入
  • 加载marshal后得到的是整个模块的代码对象,如果要单独提取每个函数的字节码,还需要遍历模块代码对象的常量区,筛选出类型为代码对象的内容

完整可用实现代码

import os
import dis
import marshal
import py_compile
from io import StringIO

# 配置路径
SOURCE_PATH = r'C:/mydirectorycomeshere/SourceCodeChecker/'
OUTPUT_PATH = r'C:/mydirectorycomeshere/bytecode_output/'
os.makedirs(OUTPUT_PATH, exist_ok=True)

# 适配不同Python版本的pyc头长度
header_size = 8
if tuple(map(int, os.sys.version.split('.')[:2])) >= (3,6):
    header_size = 12
if tuple(map(int, os.sys.version.split('.')[:2])) >= (3,7):
    header_size = 16

def get_all_code_objs(code_obj, result=None):
    """递归提取所有代码对象(包括模块、函数、嵌套函数)"""
    if result is None:
        result = []
    result.append(code_obj)
    for const in code_obj.co_consts:
        if type(const).__name__ == 'code':
            get_all_code_objs(const, result)
    return result

# 第一步:编译所有py文件为pyc
py_files = []
for root, _, files in os.walk(SOURCE_PATH):
    for f in files:
        if f.endswith('.py'):
            full_path = os.path.join(root, f)
            py_files.append(full_path)
            py_compile.compile(full_path)

# 第二步:读取pyc文件提取字节码
for py_path in py_files:
    # 生成对应pyc的路径,适配Python3.2+的pyc命名规则
    py_name = os.path.basename(py_path).rsplit('.',1)[0]
    pyc_name = f"{py_name}.cpython-{os.sys.version_info.major}{os.sys.version_info.minor}.pyc"
    pyc_path = os.path.join(os.path.dirname(py_path), '__pycache__', pyc_name)
    if not os.path.exists(pyc_path):
        continue
    
    # 读取pyc提取代码对象
    with open(pyc_path, 'rb') as f:
        f.seek(header_size)
        module_code = marshal.load(f)
    
    # 提取所有代码对象生成字节码
    all_codes = get_all_code_objs(module_code)
    output_content = []
    for idx, code in enumerate(all_codes):
        out = StringIO()
        dis.dis(code, file=out)
        code_name = code.co_name if code.co_name != '<module>' else '顶层代码'
        output_content.append(f"===== 代码块{idx}: {code_name} =====\n{out.getvalue()}\n")
    
    # 保存到输出文件
    output_file = os.path.join(OUTPUT_PATH, f"{py_name}_bytecode.txt")
    with open(output_file, 'w', encoding='utf-8') as f:
        f.write('\n'.join(output_content))

print("所有字节码已生成完成")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 19:15:08