如何让Python项目中所有未捕获异常附带时间戳输出到标准输出
我懂你的需求——不用纠结这个websocket连接关闭的异常原因,就是想让所有没被捕获的异常在打印的时候都带上时间戳对吧?下面给你两种实用的实现方式,覆盖主线程和子线程的场景:
1. 处理主线程的未捕获异常:重写sys.excepthook
Python的sys.excepthook是全局处理未捕获异常的钩子,我们可以重写它,在输出异常栈前加上时间戳:
import sys import traceback from datetime import datetime def timestamp_excepthook(type, value, tb): # 获取当前时间并格式化 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 先打印时间戳 print(f"[{timestamp}] Uncaught exception:") # 再打印原本的异常栈信息 traceback.print_exception(type, value, tb) # 替换默认的excepthook sys.excepthook = timestamp_excepthook
把这段代码放在你项目的入口文件最开始的位置(比如client.py的开头),主线程里的未捕获异常就会自动带上时间戳了。
2. 处理子线程的未捕获异常:自定义线程类
你遇到的异常是在Thread-1里的,而默认的sys.excepthook不会处理子线程的未捕获异常。我们需要自定义线程类,重写run方法来捕获线程内的异常并添加时间戳:
import threading import traceback from datetime import datetime class TimestampThread(threading.Thread): def run(self): try: # 执行原本的线程逻辑 super().run() except Exception as e: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{timestamp}] Exception in thread {self.name}:") traceback.print_exc()
然后在你的代码里,创建线程的时候用这个自定义类代替原来的threading.Thread。比如你代码里的Timer(Timer是Thread的子类),可以这样修改:
# 原来的代码: # self.keepAliveTimer = Timer(15, lambda: self.sendKeepAlive()) # 修改后: from threading import Timer class TimestampTimer(TimestampThread, Timer): pass self.keepAliveTimer = TimestampTimer(15, lambda: self.sendKeepAlive())
这样子线程里的未捕获异常也会带上时间戳输出了。
验证效果
修改后,再触发异常的话,输出会变成类似这样:
[2024-05-20 14:35:22] Exception in thread Thread-1:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
...(后面是原本的异常栈)
内容的提问来源于stack exchange,提问作者Shashwat Kumar

