需求与解决方案
当日志打印量较大或频率较高时,为避免日志输出影响代码主流程执行,可采用异步方式实现日志记录。
示例代码
import logging
import logging.handlers
import queue
# 配置主日志记录器
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
# 创建队列
log_queue = queue.Queue()
# 创建队列处理器
queue_handler = logging.handlers.QueueHandler(log_queue)
root_logger.addHandler(queue_handler)
# 创建实际的日志处理器(如文件处理器)
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
# 创建队列监听器
queue_listener = logging.handlers.QueueListener(log_queue, file_handler)
queue_listener.start()
def main():
logger = logging.getLogger(__name__)
for i in range(1000):
logger.debug(f"Logging message {i}")
if __name__ == "__main__":
try:
main()
finally:
# 停止队列监听器
queue_listener.stop()
基于 QueueHandler、FileHandler 和 QueueListener 的交互流程
初始化配置阶段
- 创建队列:构建
queue.Queue对象,用于临时存储待处理的日志记录,后续日志消息皆存放于此。 - 配置队列处理器(QueueHandler):添加至主日志记录器,作用为拦截主日志记录器生成的所有日志记录,并将其存入之前创建的队列,类似 “调度员”。
- 配置文件处理器(FileHandler):创建
FileHandler对象,负责将日志记录写入文件,可设置日志级别与格式,如指定日志文件路径、输出格式(时间、日志级别、日志消息等)。 - 配置队列监听器(QueueListener):创建
QueueListener对象,传入队列与文件处理器。其在单独线程运行,持续监听队列,一旦队列中有新日志记录,就取出传递给文件处理器。
日志记录阶段
- 日志产生:代码中调用
logger记录日志,如logger.debug("Some debug message"),主日志记录器生成日志记录。 - 日志入队:由于
QueueHandler已添加到主日志记录器,该日志记录会被QueueHandler拦截并放入队列。此时主程序可继续执行,无需等待日志实际处理完成,避免影响主程序性能。
日志处理阶段
- 日志监听与传递:
QueueListener在单独线程持续监听队列,一旦发现新日志记录,立即从队列中取出。 - 日志写入文件:
QueueListener将取出的日志记录传递给FileHandler,FileHandler按配置的日志级别与格式,将日志记录写入指定文件。
程序结束阶段
调用QueueListener的stop方法,确保队列中剩余日志记录处理完毕,停止监听队列,释放相关资源。
总结:QueueHandler负责将日志记录放入队列,QueueListener负责从队列取出日志记录传递给FileHandler,FileHandler负责将日志记录写入文件,三者协同实现异步日志记录功能
1186






