Python脚本无异常却触发告警邮件问题求助
嘿,我来帮你排查下这个棘手的问题——明明脚本正常跑完,却还是收到告警邮件,这说明你的main()里的except块被意外触发了,说白了就是脚本运行过程中其实抛出了你没察觉到的异常,咱们一步步拆解问题:
最可能的几个原因&修复方案
1. 缺失核心模块导入
我注意到你的run_script()里用到了requests和json,但代码开头完全没导入这俩模块!如果脚本在Windows任务计划里运行时,因为找不到这些模块抛出ImportError,就会直接触发外层的except块发邮件。
赶紧补上导入语句:
import requests import json
2. 内部异常捕获范围太窄
你在run_script()里只捕获了KeyExistsError,但实际执行中可能出现其他异常——比如网络请求失败的requests.exceptions.RequestException、字典键不存在的KeyError等等,这些异常会跳过内部的try-except,直接被外层的except Exception as e捕获,进而触发告警。
如果这些内部异常属于你预期内的情况,不想触发告警,可以扩大内部捕获范围:
try: ---Do an action--- except Exception as inner_e: --- 如果有异常就执行其他操作 --- # 顺便记个日志,方便后续排查 logging.error(f"内部操作出错: {inner_e}")
或者明确列出所有可能出现的异常类型,避免遗漏。
3. 邮件初始化逻辑的小问题
你把邮件消息message的初始化放在了全局作用域,虽然概率不高,但如果脚本在任务计划中多次执行,可能会因为残留状态导致意外触发。建议把邮件初始化移到send_email()函数内部,还能顺便把异常信息塞进邮件里:
def send_email(e): # 邮件内容带上异常详情,方便排查 mail_content = f'Hi, 脚本执行出现异常:\n{str(e)}' sender_address = '<sender_address>' sender_pass = '<password>' receiver_address = ['receiver_address1', 'receiver_address2'] message = MIMEMultipart() message['From'] = sender_address message['Subject'] = 'PROD ShipTime Script 异常告警' message['To'] = ", ".join(receiver_address) message.attach(MIMEText(mail_content, 'plain')) # SMTP发送逻辑保持不变 session = smtplib.SMTP('smtp.gmail.com', 587) session.ehlo() session.starttls() session.login(sender_address, sender_pass) text = message.as_string() session.sendmail(sender_address, receiver_address, text) session.quit()
4. Windows任务计划的环境坑
有时候任务计划的执行环境和你本地测试完全不一样:比如脚本路径写错了、用户权限不足、Python解释器路径配置错误等等,这些都会导致脚本运行出错但你没直观感受到。
建议给脚本加个日志功能,把执行状态和异常信息记录下来:
# 初始化日志配置 logging.basicConfig( filename='script_run.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) def main(): try: logging.info("脚本开始执行") run_script() logging.info("脚本执行成功") except Exception as e: logging.error(f"脚本执行出错: {str(e)}", exc_info=True) send_email(e) print(e) print("Email Sent Successfully")
之后查看script_run.log就能清晰看到脚本到底是成功了还是在哪一步出了问题。
总结
先补全模块导入,这是最常见的“隐形异常”原因;然后通过日志明确脚本执行状态,再根据实际情况调整异常捕获逻辑,应该就能解决这个问题了。
内容的提问来源于stack exchange,提问作者Nik

