在真实项目中,Debug 代码通常包括:
print()logging.debug()logging.info()logger.debug()- 临时调试函数(如
debug()、pprint()) if DEBUG:块
👉手动删除不现实,正则又极易误伤
👉AST 是唯一靠谱、可维护的方案
本文教你如何用Python AST 自动、安全地移除 Debug 代码。
一、为什么不能用正则?
错误示例:
# 误删print=my_printprint("hello")# 不该删text="print(x)"# 字符串正则不知道「语义」,而 AST 知道。
二、我们要移除哪些 Debug 代码?
本文支持移除:
| 类型 | 示例 |
|---|---|
print(x) | |
| logging.debug | logging.debug(x) |
| logging.info | logging.info(x) |
| logger.debug | logger.debug(x) |
| if DEBUG | if DEBUG: ... |
三、核心思路(AST 级别)
- 把代码解析成 AST
- 遍历所有语句节点
- 命中 Debug → 直接删除节点
- 重新生成源码
关键工具:
👉ast.NodeTransformer
四、完整实现代码(推荐直接用)
1️⃣ Debug 代码移除器
importastimportastor DEBUG_FUNC_NAMES={"print","pprint","debug",}LOGGING_METHODS={"debug","info",}classRemoveDebugTransformer(ast.NodeTransformer):defvisit_Expr(self,node):""" 处理: - print(...) - logging.debug(...) - logger.debug(...) """call=node.valueifnotisinstance(call,ast.Call):returnnode func=call.func# print(...)ifisinstance(func,ast.Name):iffunc.idinDEBUG_FUNC_NAMES:returnNone# logging.debug(...) / logger.debug(...)ifisinstance(func,ast.Attribute):iffunc.attrinLOGGING_METHODS:returnNonereturnnodedefvisit_If(self,node):""" 处理: if DEBUG: ... """# if DEBUG:ifisinstance(node.test,ast.Name)andnode.test.id=="DEBUG":returnNonereturnself.generic_visit(node)2️⃣ 对外调用函数
defremove_debug_code(code:str)->str:tree=ast.parse(code)transformer=RemoveDebugTransformer()tree=transformer.visit(tree)ast.fix_missing_locations(tree)returnastor.to_source(tree)五、测试示例
原始代码
importlogging DEBUG=Trueprint("hello")logging.debug("debug log")logging.info("info log")logger.debug("logger debug")x=10ifDEBUG:print("only debug")print("done")执行清理
code=""" import logging DEBUG = True def foo(x): print("foo x =", x) logging.debug("debug foo") logging.info("info foo") if DEBUG: print("only in debug") return x * 2 print("program start") result = foo(10) print("result =", result) """new_code=remove_debug_code(code)print(new_code)清理后结果
importlogging x=10print("done")✅ Debug 代码全部移除
✅ 正常业务代码保留
✅ 不影响 import / 变量 / 逻辑
六、进阶场景(非常实用)
🔹 1. 只在生产环境移除
ifos.getenv("ENV")=="prod":code=remove_debug_code(code)🔹 2. 保留 logging.warning / error
只需修改:
LOGGING_METHODS={"debug","info"}🔹 3. 移除 assert(生产环境)
defvisit_Assert(self,node):returnNone🔹 4. 批量清洗项目代码
frompathlibimportPathforfileinPath("src").rglob("*.py"):code=file.read_text(encoding="utf-8")new_code=remove_debug_code(code)file.write_text(new_code,encoding="utf-8")七、为什么 AST 是「终极方案」
| 方案 | 安全性 | 可维护 | 可扩展 |
|---|---|---|---|
| 正则 | ❌ | ❌ | ❌ |
| 手动删 | ❌ | ❌ | ❌ |
| AST | ✅ | ✅ | ✅ |
AST 的优势是:
👉按语义删代码,而不是按字符串
八、适合哪些场景?
- 上线前自动清理 Debug
- CI/CD 中做代码净化
- 训练大模型前清洗代码语料
- 代码混淆 / 防逆向
- 企业级代码审计