Python脚本运行异常时自动发送含具体报错信息邮件的实现方法
实现方案
你现有代码的核心问题有3个:
- 日志初始化逻辑全部写在
except异常捕获块内,程序正常运行时根本没有加载日志、SMTP邮件配置,逻辑顺序完全颠倒 - 捕获到异常后仅打印固定提示,没有将实际的异常栈、错误详情传入日志,导致邮件只能发送你硬编码的固定内容
- SMTPHandler的日志级别设置为
CRITICAL,仅当你手动调用logger.critical()时才会触发邮件,普通异常触发的ERROR级别日志不会触发邮件发送
修改步骤
- 把所有日志、SMTP邮件handler的初始化逻辑移到程序入口最开头,保证程序启动时就完成日志配置
- 将SMTPHandler的触发级别调整为
logging.ERROR,只要出现错误级别的日志就自动发邮件 - 异常捕获块内使用
logger.exception()方法记录错误,该方法会自动捕获当前异常的完整栈信息、错误详情,自动带入日志内容,不需要手动拼接错误信息 - 修正原有代码的缩进错误(原有代码中
try块没有缩进在main函数内部,属于语法错误)
修改后可直接运行的示例代码
import csv import sys import logging import logging.handlers # 导入自有业务依赖 # import whg_common # from your_utils import dateutil, fileutil def init_logger(): # 统一初始化日志配置 logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 控制台输出配置 consoleHandler = logging.StreamHandler(sys.stdout) consoleHandler.setLevel(logging.DEBUG) consoleHandler.setFormatter(formatter) logger.addHandler(consoleHandler) # 本地轮转日志配置 fileHandler = logging.handlers.RotatingFileHandler( filename="error.log", maxBytes=1024000, backupCount=10, mode="a" ) fileHandler.setLevel(logging.INFO) fileHandler.setFormatter(formatter) logger.addHandler(fileHandler) # 错误邮件通知配置 smtpHandler = logging.handlers.SMTPHandler( mailhost=('email.xxxxx.com', 25), fromaddr="Automation@xxxxx.net", toaddrs=["abc@xxx.net"], # 多个收件人传字符串列表即可 subject="CSV自动化处理流程报错", credentials=("automation@xxxxx.net", "xxxxx"), secure=() ) smtpHandler.setLevel(logging.ERROR) # 错误级别即触发邮件 smtpHandler.setFormatter(formatter) logger.addHandler(smtpHandler) return logger # 程序启动第一步先完成日志初始化 logger = init_logger() def main(): try: # 所有业务逻辑全部放在try块内,任意步骤报错都会被捕获 configuration = whg_common.readApplicationConfiguration() rows = [] d = {} with open("/Users/Dell/prewhg-cleansender/File_Processing/dailyfile/Test2020_20220521_032516.csv") as f: spamreader = csv.DictReader(f, delimiter=',', quotechar='"') with open("/Users/Dell/prewhg-cleansender/File_Processing/dailyfile/output.csv", 'w') as g: for row in spamreader: rows.append(row) row['StreetNum'] = row['Address1'].split(' ')[0] row['Finitial'] = row['Last Name'][0:1] row['UniqueID'] = row['Client ID'] + row['StreetNum'] + row['Zip'] + row['Zip+4'] + row['Finitial'] row['date'] = dateutil.getToday().strftime("%Y/%m/%d") unique = row['UniqueID'] if unique not in d: d[unique] = row del row['StreetNum'] del row['Finitial'] fileutil.writeFile("/Users/Dell/prewhg-cleansender/File_Processing/dailyfile/output.csv", rows) logger.info("CSV文件处理流程执行完成") except Exception: # 自动记录完整错误栈,同时触发邮件发送,邮件自带全部错误详情 logger.exception("文件处理流程运行异常") if __name__ == "__main__": main()
效果说明
- 程序正常运行无报错时,不会触发任何邮件发送,仅在控制台、本地日志文件记录运行信息
- 任意业务步骤抛出异常时,会自动发送邮件,邮件内容包含报错时间、异常类型、具体报错信息、完整代码调用栈,可直接定位到出错代码行
- 本地日志文件会同时留存所有INFO级别以上的运行记录,方便后续回溯问题
内容的提问来源于stack exchange,提问作者Kcostanzo
相关产品推荐
相关产品推荐

