为什么 TimedRotatingFileHandler 不能正常工作以及如何解决这个问题(轮换工作,但缺少日志行)当日志行
Why doesn't TimedRotatingFileHandler work properly and how to solve this issue(rotation is working, but missing logging lines) when log lines
更新:
TimedRotatingFileHandler
在我使用 multiprocessing
时无法正常工作,我应该如何处理多处理日志记录?
我编写了自己的 Logger class,如下所示,将其用作所有其他 python 脚本中的模块。
import logging
import logging.handlers
class Logger:
DEFAULT_LOG_OUTPUT = "/home/haifzhan/"
def __init__(self, logger_name, log_file_name, log_dir=DEFAULT_LOG_OUTPUT, log_level=logging.DEBUG):
self.logger = logging.getLogger(logger_name,)
self.formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
#self.file_handler = logging.FileHandler(log_dir + log_file_name)
file_path = log_dir + log_file_name
self.file_handler = logging.handlers.TimedRotatingFileHandler(file_path, when='H', backupCount=30)
self.file_handler.setFormatter(self.formatter)
self.logger.setLevel(log_level)
self.logger.addHandler(self.file_handler)
self.console_handler = logging.StreamHandler()
self.console_handler.setFormatter(self.formatter)
self.console_handler.setLevel(logging.DEBUG)
self.logger.addHandler(self.console_handler)
def get_logger(self):
return self.logger
在我的 python 脚本的顶部,我创建了一个 Logger 实例。
`logger = Logger("logger name", "logfile.log", log_dir=LOG_DIR, log_level=logging.INFO).get_logger()` # always put it at the top of my script
当我使用 FileHandler
时它工作得很好,不幸的是它 在我切换到 TimedRotatingFileHandler
后忽略了日志行 。日志文件轮换按预期工作,但不记录所有行。控制台日志记录工作正常,怎么可能?
self.file_handler = logging.FileHandler(log_dir + log_file_name)
self.file_handler = logging.handlers.TimedRotatingFileHandler(file_path, when='H', backupCount=30)
谁能帮忙解决一下?
每个进程都需要一个单独的日志文件。
不要使用来自所有进程的文件。相反,制作一些日志消息队列并让一个专用进程(主要进程或特殊进程)执行日志记录。
这应该会消除进程之间的竞争条件和那些问题。
鉴于您已经设置了Logger
class,实施应该很容易。您可以拥有一个日志记录 Queue
的全局/单例实例(其中每个 Logger
实例 put
它们的日志)并从单个中央进程管理实际的日志记录事项。
编辑:一种可能的方法是使用特殊处理程序:
class QueueLogger(Handler):
def __init__(self, log_queue):
"""
Initialize the handler with logging Queue.
"""
Handler.__init__(self)
self.log_queue = log_queue
def emit(self, record):
self.log_queue.put(record)
这将允许将记录(包含日志级别和额外信息)放入队列中。另一方面,你可以有一个 HubLogger,它会做类似的事情:
while True:
r = log_queue.get()
my_handler.emit(r)
并且 my_handler
可以是 TimedRotatingFileHandler
或您想要的任何处理程序。
归功于@unutbu,因为他们已经在评论中评论了 "Hub" 方法。
更新:
TimedRotatingFileHandler
在我使用 multiprocessing
时无法正常工作,我应该如何处理多处理日志记录?
我编写了自己的 Logger class,如下所示,将其用作所有其他 python 脚本中的模块。
import logging
import logging.handlers
class Logger:
DEFAULT_LOG_OUTPUT = "/home/haifzhan/"
def __init__(self, logger_name, log_file_name, log_dir=DEFAULT_LOG_OUTPUT, log_level=logging.DEBUG):
self.logger = logging.getLogger(logger_name,)
self.formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
#self.file_handler = logging.FileHandler(log_dir + log_file_name)
file_path = log_dir + log_file_name
self.file_handler = logging.handlers.TimedRotatingFileHandler(file_path, when='H', backupCount=30)
self.file_handler.setFormatter(self.formatter)
self.logger.setLevel(log_level)
self.logger.addHandler(self.file_handler)
self.console_handler = logging.StreamHandler()
self.console_handler.setFormatter(self.formatter)
self.console_handler.setLevel(logging.DEBUG)
self.logger.addHandler(self.console_handler)
def get_logger(self):
return self.logger
在我的 python 脚本的顶部,我创建了一个 Logger 实例。
`logger = Logger("logger name", "logfile.log", log_dir=LOG_DIR, log_level=logging.INFO).get_logger()` # always put it at the top of my script
当我使用 FileHandler
时它工作得很好,不幸的是它 在我切换到 TimedRotatingFileHandler
后忽略了日志行 。日志文件轮换按预期工作,但不记录所有行。控制台日志记录工作正常,怎么可能?
self.file_handler = logging.FileHandler(log_dir + log_file_name)
self.file_handler = logging.handlers.TimedRotatingFileHandler(file_path, when='H', backupCount=30)
谁能帮忙解决一下?
每个进程都需要一个单独的日志文件。
不要使用来自所有进程的文件。相反,制作一些日志消息队列并让一个专用进程(主要进程或特殊进程)执行日志记录。
这应该会消除进程之间的竞争条件和那些问题。
鉴于您已经设置了Logger
class,实施应该很容易。您可以拥有一个日志记录 Queue
的全局/单例实例(其中每个 Logger
实例 put
它们的日志)并从单个中央进程管理实际的日志记录事项。
编辑:一种可能的方法是使用特殊处理程序:
class QueueLogger(Handler):
def __init__(self, log_queue):
"""
Initialize the handler with logging Queue.
"""
Handler.__init__(self)
self.log_queue = log_queue
def emit(self, record):
self.log_queue.put(record)
这将允许将记录(包含日志级别和额外信息)放入队列中。另一方面,你可以有一个 HubLogger,它会做类似的事情:
while True:
r = log_queue.get()
my_handler.emit(r)
并且 my_handler
可以是 TimedRotatingFileHandler
或您想要的任何处理程序。
归功于@unutbu,因为他们已经在评论中评论了 "Hub" 方法。