作者声明
本文非原创理论研究。“边界校验”“EAFP”“只捕获可处理异常”“let it crash"等思想在软件工程领域已有成熟论述(CMU讲义、Erlang社区、Google SRE手册等)。
本文仅以"空圈容错"为口径,将这些工程直觉梳理为可执行规则,并给出Python实现。
文中"空圈"为笔者元理论术语,等价于"安全空状态”。完整理论参见《空圈容错:从"安全空状态"到系统韧性》。
一、一个被误解的“容错”语法
很多教程会教这样写:


python
try:
risky_operation()
except Exception:
pass # 出错就算了
纯文本

这常被称为“容错”,但从工程角度看,这更接近掩耳盗铃。
except Exception 捕获了所有异常,然后不做任何处理。错误没有被修复,只是被吞掉。系统继续运行,但内部状态可能已经不一致——数据写了一半、连接没关、锁没释放。
真正的容错,目标不是“不让错发生”,而是:在错误发生时,让系统停留在“安全状态”,而不是“未知状态”。
二、从空圈容错到Python异常处理的三级边界
2.1 空圈容错的核心直觉
空圈容错理论的核心直觉是:系统在遭遇扰动时,可以预设一个“安全空状态”(记作 ∅_safe),用它吸收不确定性,避免系统直接进入崩溃态(记作 ⊥)。
其元公式为:
稳态 ⇔ 边界力 ∈ [D_min, D_max(技术栈)]
低于 D_min,扰动压垮缓冲;高于 D_max,系统自身的不稳定性导致解体。
2.2 C/M/P三层拓扑映射到Python
| C层(主干承载) | 业务逻辑的正常执行 | 不允许静默吞异常,否则C层状态不可信 |
| M层(收容吸收) | except捕获、stop重试上限、wait退避策略 | 只捕获能处理的异常,区分暂时性/永久性故障 |
| P层(冗余备份) | 异常分层处理、降级返回默认值 | 顶层入口兜底,返回安全空值 |
2.3 推导出的三条原则
原则一:接口与API设计层——用“空”做安全垫


python
常见写法
if data is not None:
for item in data:
process(item)
容错写法
for item in (data or []):
process(item)
纯文本

None、空列表、空字典是“安全默认值”。它们不会引发异常,允许系统“空转”而非“崩溃”。
原则二:运行时层——只捕获你能处理的


python
try:
result = call_api()
except TimeoutError:
log.warning(“API 超时,走降级逻辑”)
result = DEFAULT_VALUE
except ValueError as e:
log.error(f"参数错误,需人工介入:{e}")
raise # 不知道怎么处理,让它冒泡
纯文本

原则三:架构层——区分“暂时性”与“永久性”故障


python
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=1, max=10)
)
def call_unstable_api():
可能临时失败的外部调用
…
纯文本

三、从原则到规则:PY-FAULT体系
3.1 为什么需要自动化检查
“应该怎么做”和“实际怎么做”之间有差距。人工审查无法覆盖所有代码,需要自动化工具强制执行。
3.2 PY-FAULT规则表(V1.0-6.4)
| C层底线 | except Exception: pass | PY000 | ERROR | ✅ 已实现 |
| C层底线 | except BaseException | PY001 | ERROR | ✅ 已实现 |
| M层收容 | @retry()无stop | PY002 | ERROR | ✅ 已实现 |
| M层收容 | 重试永久异常 | PY003 | ERROR | ✅ 已实现 |
| M层缓冲 | @retry()无wait | PY004 | WARNING | ✅ 已实现 |
| P层冗余 | 顶层入口无兜底 | — | WARNING | 🔜 规划中 |
四、工具实现:retry_sast.py
基于上述规则,实现了静态扫描工具 retry_sast.py。
4.1 核心代码片段


python
检查PY000:except分支仅pass
def h06_py000(handler: ast.ExceptHandler) -> List[Dict[str, Any]]:
alerts = []
if len(handler.body) == 1 and isinstance(handler.body[0], ast.Pass):
alerts.append(make_alert(
“PY000 ERROR”,
handler.lineno,
“except分支仅pass,静默吞掉异常,禁止直接pass捕获异常”
))
return alerts
检查PY002:@retry缺少stop
def check_stop_valid(call_node: ast.Call) -> bool:
for kw in call_node.keywords:
if kw.arg == “stop”:
return True
return False
纯文本

4.2 测试验证
- 测试用例:40个(30个有告警,10个无告警)
- 覆盖场景:基础单规则、异步函数、类内部方法、入口白名单豁免、别名装饰器
五、总结
try/except 不是万能膏药。真正的容错是:
这套原则从空圈容错理论的C/M/P三层拓扑推导而来,并已实现为可自动执行的检查工具 retry_sast.py。
再次声明
本文为基于公开工程实践的梳理与再表述,非原创理论研究。
代码示例仅为示意,建议结合实际场景验证后再落地。
容错策略需结合具体业务场景调整,不可盲目套用。
欢迎来自一线SRE/后端开发的反例补充。
本文由本人与元宝共同创作,经千问 、豆包、DeepSeek交叉校验完成。
脚本网址
https://gitee.com/liaiyangshi/kongquan-fault-tolerant-theory



