You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python脚本运行异常时自动发送含具体报错信息邮件的实现方法

实现方案

你现有代码的核心问题有3个:

  • 日志初始化逻辑全部写在except异常捕获块内,程序正常运行时根本没有加载日志、SMTP邮件配置,逻辑顺序完全颠倒
  • 捕获到异常后仅打印固定提示,没有将实际的异常栈、错误详情传入日志,导致邮件只能发送你硬编码的固定内容
  • SMTPHandler的日志级别设置为CRITICAL,仅当你手动调用logger.critical()时才会触发邮件,普通异常触发的ERROR级别日志不会触发邮件发送

修改步骤

  1. 把所有日志、SMTP邮件handler的初始化逻辑移到程序入口最开头,保证程序启动时就完成日志配置
  2. 将SMTPHandler的触发级别调整为logging.ERROR,只要出现错误级别的日志就自动发邮件
  3. 异常捕获块内使用logger.exception()方法记录错误,该方法会自动捕获当前异常的完整栈信息、错误详情,自动带入日志内容,不需要手动拼接错误信息
  4. 修正原有代码的缩进错误(原有代码中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 09:15:43