如何消除Python异常处理中的重复日志条目?
日志重复问题解决
需求说明
当函数触发外层异常时,尝试读取文件123:
- 若文件读取失败,记录内层异常,且不重复输出外层异常的回溯信息
- 若文件读取成功,仅记录外层异常日志
原代码
import logging logging.basicConfig(filename='test.log', filemode='a', level=logging.DEBUG) logger = logging.getLogger("my_logger") def my_div(a, b): try: return a/b except Exception as e: # outer exception try: with open('123', 'rb') as fi: pass except Exception as e1: # inner exception logger.exception(f"inner error\n{storage}") logger.exception(f"outer error\n{storage}") storage = {} for i in [1,0]: storage[i] = my_div(2, i)
问题现象
运行后日志中出现外层异常回溯重复:
ERROR:my_logger:inner error {1: 2.0} Traceback (most recent call last): File "D:/workspace/acne/src/scratch/logger_related/minimal_logger.py", line 9, in my_div return a/b ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "D:/workspace/acne/src/scratch/logger_related/minimal_logger.py", line 12, in my_div with open('123', 'rb') as fi: FileNotFoundError: [Errno 2] No such file or directory: '123' ERROR:my_logger:outer error {1: 2.0} Traceback (most recent call last): # 需移除该重复条目 File "D:/workspace/acne/src/scratch/logger_related/minimal_logger.py", line 9, in my_div return a/b ZeroDivisionError: division by zero
问题原因
logger.exception()会自动捕获当前上下文的异常栈,当内层except块执行完后,外层的except块依然持有原始的ZeroDivisionError异常上下文,此时再次调用logger.exception()就会重复输出该异常的回溯信息。
解决方案
根据需求调整日志记录逻辑:
- 当内层异常触发时,仅记录内层异常,不再重复记录外层异常
- 当内层无异常(文件读取成功),再记录外层异常
修改后的代码如下:
import logging logging.basicConfig(filename='test.log', filemode='a', level=logging.DEBUG) logger = logging.getLogger("my_logger") def my_div(a, b): try: return a/b except Exception as e: # outer exception file_read_success = False try: with open('123', 'rb') as fi: pass file_read_success = True except Exception as e1: # inner exception # 记录内层异常,自动包含外层异常的上下文 logger.exception(f"inner error\n{storage}") if file_read_success: # 文件读取成功时,仅记录外层异常 logger.error(f"outer error\n{storage}", exc_info=e) storage = {} for i in [1,0]: storage[i] = my_div(2, i)
说明
- 用
file_read_success标记文件是否读取成功 - 内层异常触发时,
logger.exception()会自动附带外层异常的上下文(即During handling of the above exception...部分),无需额外记录外层异常 - 文件读取成功时,使用
logger.error()并通过exc_info=e指定要记录的外层异常,避免重复捕获上下文
内容的提问来源于stack exchange,提问作者sixtytrees
相关产品推荐
相关产品推荐

