Python 多进程下日志打印

Python 多进程下日志打印

问题分析

使用 gunicorn 启动 Flask 时,如果直接使用 logging 的 RotatingFileHandler 模块会出现日志混乱,甚至日志丢失的情况。
在日志翻转时,可能出现一个进程将 log 文件翻转,而后又有进程也将 log 文件翻转,导致 log.1 文件并未达到设置的最大的文件大小,而第一个进程也继续再往 log.1 中输出日志。

改进方式

根据网上很多文档,使用 portalocker 创建文件锁,实现了一个简单的 handler 方便使用,暂时没有发现问题。
需要安装依赖:pip install portalocker

import logging
import logging.handlers
import os
import time
from logging.handlers import RotatingFileHandler
import portalocker
def get_lock_filename(log_file_name) -> str:
"""
定义日志文件锁名称,类似于 `.__file.lock`,其中file与日志文件baseFilename一致
:return:
"""
if log_file_name.endswith('.log'):
lock_file = log_file_name[:-4]
else:
lock_file = log_file_name
lock_file += '.lock'
lock_path, lock_name = os.path.split(lock_file)
# hide the file on Unix and generally from file completion
lock_name = '.__' + lock_name
return str(os.path.join(lock_path, lock_name))
class ConcurrentRotatingFileHandler(RotatingFileHandler):
def __init__(self, filename, *args, **kwargs):
super().__init__(filename, *args, **kwargs)
file_dir = os.path.split(filename)[0]
if not os.path.exists(file_dir):
os.makedirs(file_dir)
lock_filename = get_lock_filename(filename)
self.concurrent_lock = portalocker.Lock(lock_filename, flags=portalocker.LOCK_EX)
def _do_rollover(self, record):
# 检查日志文件是否需要翻转
base_stream = self._open()
base_stream.seek(0, 2)
msg = "%s\n" % self.format(record)
base_stream_length = base_stream.tell() + len(msg)
base_stream.close()
if base_stream_length >= self.maxBytes:
# print('current pid: %d, doRollover' % os.getpid())
super().doRollover()
else:
if self.stream:
self.stream.close()
self.stream = None
if not self.delay:
self.stream = self._open()
def emit(self, record):
"""
Emit a record.
Output the record to the file, catering for rollover as described
in doRollover().
"""
with self.concurrent_lock:
try:
if self.shouldRollover(record):
# print('current pid: %d, shouldRollover: %d' % (os.getpid(), self.shouldRollover(record)))
self._do_rollover(record)
logging.FileHandler.emit(self, record)
except Exception:
self.handleError(record)
posted @   守望人间  阅读(106)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示