pycdc 上手指南:从 .pyc 还原 Python 源码
有一次,我需要弄明白一个陈年 .pyc 里到底藏着什么逻辑,源代码早丢了。这种时候,pycdc 就能派上用场。
pycdc 是用 C++ 开发的 Python 字节码反编译工具,支持 1.0 到 3.13 全系版本。它包含两个核心部分:pycdas 负责反汇编,输出字节码指令;pycdc 则直接生成 Python 源码。我用过几个同类的工具,pycdc 在版本兼容和还原精度上做得最扎实,虽然偶尔也会有点小毛病。
编译安装
用 CMake 构建,没什么特别的:
git clone <project_repo>
cd pycdc
cmake -DCMAKE_BUILD_TYPE=Release .
make -j$(nproc)
Release 模式足够日常使用,需要调试时换成 Debug。
基本用法
最常见的场景:源码丢了,只剩 .pyc。直接反编译:
./pycdc important_script.pyc
如果你只关心字节码长什么样,想看看解释器怎么处理指令的,用 pycdas:
./pycdas third_party_module.pyc
不同 Python 版本的字节码格式差异很大,pycdc 能自动识别,但出错时最好用 -v 明确指定版本:
# Python 2.7 老代码
./pycdc -v 2.7 legacy_code.pyc
# 3.11 引入的新字节码特性
./pycdc -v 3.11 modern_feature.pyc
一次处理多个文件
真要批量搞一堆 .pyc,一个 for 循环就够了:
#!/bin/bash
for file in *.pyc; do
echo "处理文件:$file"
./pycdc "$file" > "${file%.pyc}.py"
done
我习惯把输出重定向到文件,然后手动检查一遍——自动反编译偶尔会在代码间插入奇怪的空行,或者缩进不太对。
验证反编译效果
项目自带了测试脚本,可以用来检验反编译的准确性:
# 跑指定测试用例
python tests/run_tests.py --filter test_functions
# 多进程并行,快很多
python tests/run_tests.py -j 4
测试覆盖了表达式、控制流、异常处理等场景,自己修改源码后跑一遍测试很有用。
内部工作流程
pycdc 背后大致是三个步骤:字节码解析 → 构建抽象语法树(AST)→ 生成源代码。解析部分由 pyc_code.cpp 和 bytecode.cpp 处理,AST 的构建在 ASTree.cpp 里,最后输出可读代码。分层的好处是,适配新 Python 版本时,只要在 bytes 目录下加对应的解析模块,不用大改其他逻辑。

