暗无天日

=============>DarkSun的个人博客

TIL:Python 中不该 catch 的三种异常

Python Morsels 的一篇文章中学到三个反直觉的判断。原则就一条,只 catch 你理解来源的异常。有几种异常看着该 catch,但其实不该。

NameError 是代码 bug,别 catch

NameError 就是变量名拼错了。你 catch 它等于把自己的 bug 藏起来,跟用户数据没有半点关系。让它在开发阶段炸出来反而好。

KeyError 不该 catch,应该预处理

csv.DictReader 读 CSV,表头拼错了(start 写成 Start), row["start"] 就会抛 KeyError。有人习惯把它加到 except 里统一处理,但这么干有两个问题。

  1. 错误信息变模糊了。原始 traceback 显示 KeyError: 'start' ,你一眼就能看出是表头大小写不匹配。catch 后只能输出"Invalid date on line N",每一行都报,误导你以为数据全坏了
  2. 问题只出在表头,但循环体里 catch 让每一行都走一遍报错逻辑

正确的做法是在循环之前检查表头。

for header in ["name", "start", "end"]:
    if header not in reader.fieldnames:
        print(f"Error: Missing {header} header", file=sys.stderr)
        sys.exit(1)

报错清晰,而且只报一次。

catch all 在批量处理时是合理的

批量处理多个文件时,一个文件出错不应该中断整个流程。

for path in args.paths:
    try:
        with open(path) as f:
            line_count = sum(1 for line in f)
        print(f"{path}: {line_count} lines")
    except Exception as e:
        print(f"ERROR READING {path}: {e}", file=sys.stderr)

注意这里用的是 except Exception 而不是裸 except 。区别在于 except Exception 不会拦截 SystemExitKeyboardInterrupt ,用户按 Ctrl+C 仍然能正常退出程序。

Python : 异常处理 : exception