Python日志记录即使在使用QueueHandler QueueListener时也会减慢代码的速度

2024-03-29 15:03:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用注释中显示的链接中的示例进行了以下日志设置

我正在使用Python 3.8.5

我正在记录一些具有毫秒分辨率时间戳的数据。我发现,如果启用控制台日志(LOG.addHandler(c_queue_handler)),我的代码时间戳会显示几毫秒的延迟(我使用Wireshark比较流量)。没有控制台StreamHandler,它与Wireshark计时非常一致

我所尝试的:

  • 控制台和文件处理程序的独立侦听器,我认为这有点帮助
  • 在控制台输出中使用了如下所示的MemoryHandler,它显示的几乎与根本没有控制台处理程序一样好,但不太好。有时,在某些日志上,它会被抛出几毫秒,当它点击capacity并刷新到控制台时,可能会被抛出几毫秒

我的理解是QueueListener正在一个新线程中运行日志处理,那么为什么这会导致延迟呢?这是否只是记录器必须处理多个处理程序(而不是实际输出到控制台)的情况,因此,我无法进一步改进这一点

另外,如果我在MemoryHandler中将capacity设置为一个高的数字,当它试图将更多的数据刷新到控制台时,我会看到更大的延迟吗

import logging
import logging.handlers
import asyncio
try:
    # Python 3.7 and newer, fast reentrant implementation
    # without task tracking (not needed for that when logging)
    from queue import SimpleQueue as Queue
except ImportError:
    from queue import Queue
from typing import List

LOG = logging.getLogger('canlog')

# https://stackoverflow.com/questions/24791395/python-logging-causing-latencies
# https://www.zopatista.com/python/2019/05/11/asyncio-logging/
class LocalQueueHandler(logging.handlers.QueueHandler):
    def emit(self, record: logging.LogRecord) -> None:
        # Removed the call to self.prepare(), handle task cancellation
        try:
            self.enqueue(record)
        except asyncio.CancelledError:
            raise
        except Exception:
            self.handleError(record)

def loggingSetup():
    c_que = Queue() 
    c_queue_handler = LocalQueueHandler(c_que)
    c_hdl = logging.StreamHandler()
    listener = logging.handlers.QueueListener(c_que, c_hdl)
    formatter = logging.Formatter('[%(asctime)s %(filename)s:%(lineno)s - %(funcName)s]: %(message)s')
    LOG.setLevel(logging.DEBUG)
    

    f_que = Queue()
    f_queue_handler = LocalQueueHandler(f_que)
    f_hdl = logging.FileHandler('udsconn_log.log')
    listener2 = logging.handlers.QueueListener(f_que, f_hdl)

    memoryhandler = logging.handlers.MemoryHandler(
        capacity=100,  # Deliberately kept small to see affect of flushing
        flushLevel=logging.ERROR,
        target=c_hdl
    )
    
    c_queue_handler.setLevel(logging.INFO)
    f_queue_handler.setLevel(logging.DEBUG)
    c_hdl.setFormatter(formatter)
    f_hdl.setFormatter(formatter)

    LOG.addHandler(c_queue_handler) # Using this causes some delays
    LOG.addHandler(f_queue_handler)
    LOG.addHandler(memoryhandler)

    listener.start()
    listener2.start()

Tags: importselflog处理程序queuelogginghandlersque