装饰器中加异常捕获需用 try...except 包裹函数执行,用 except BaseException 排除 SystemExit 和 KeyboardInterrupt 后 re-raise;记录需含 traceback.format_exc();支持白名单异常忽略;发邮件前校验 SMTP 配置并从环境变量读密码;邮件内容须含环境、主机、时间、函数名、参数(脱敏)和 base64 编码 traceback;必须异步发送并设超时;捕获后须重新 raise 异常。

装饰器里怎么加异常捕获逻辑
核心是用 try...except 包住被装饰函数的执行,捕获所有未处理异常。别直接 except Exception 就完事——这会吞掉 SystemExit、KeyboardInterrupt 这类应正常退出的信号,得排除它们:
- 用
except BaseException as e捕全,再用if isinstance(e, (SystemExit, KeyboardInterrupt)):判断后raise - 记录异常时必须包含
traceback.format_exc(),否则邮件里只有错误类型和消息,没堆栈没法定位 - 装饰器参数建议支持传入白名单异常类型(如
ignore_exceptions=(requests.Timeout,)),避免网络超时这种预期异常也发告警
发邮件前要检查哪些配置项
很多失败不是代码问题,而是环境没配好。关键配置必须显式校验,不能靠报错才暴露:
-
SMTP_SERVER、SMTP_PORT、EMAIL_USER、EMAIL_PASSWORD这四个缺一不可,启动时就该assert检查,而不是等到发邮件时才smtplib.SMTPAuthenticationError - 密码别硬编码,从环境变量读取:
os.getenv("EMAIL_PASSWORD"),否则打包进镜像或上传到 Git 就泄露了 - 测试连接用
smtplib.SMTP(server, port).connect()+login(),但别在装饰器每次调用时都连——提前建好连接池或复用已认证的 SMTP 实例
报警邮件内容怎么写才有效
运维看到邮件第一反应是“这问题归谁”,内容必须带上下文,不能只扔个 traceback:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 主题固定格式:
f"[ALERT] {func.__name__} failed in {os.environ.get('ENV', 'unknown')} env",方便邮件客户端按主题过滤 - 正文至少含:发生时间(
datetime.now().isoformat())、所在服务器(socket.gethostname())、触发函数名、完整 traceback、调用时的args和kwargs(注意过滤敏感字段如 password、token) - 别用纯文本发长 traceback——用
MIMEText(..., 'plain', 'utf-8')并设置Content-Transfer-Encoding: base64,避免某些邮件客户端截断或乱码
为什么不能在装饰器里直接发邮件
同步发邮件会阻塞主业务,尤其 SMTP 延迟高或网络抖动时,可能把一个 100ms 的接口拖到几秒。真实线上必须异步:
立即学习“Python免费学习笔记(深入)”;
- 用
threading.Thread(target=send_mail, args=(...)).start()最简单,但要注意线程安全(比如共享的 SMTP 连接需加锁) - 更稳的做法是投递到队列(如 Redis +
rq或celery),但会引入新依赖;小项目用线程够用 - 务必加超时控制:
smtp.send_message(msg, timeout=5),否则网络卡死会导致线程永久挂起
最常被忽略的是异常二次抛出——装饰器捕获后若不重新 raise,上游完全感知不到失败,业务逻辑可能继续往下跑,产生脏数据。该重抛的必须重抛,邮件只是副产物。

















