【问题标题】:Python - asynchronous loggingPython - 异步日志记录
【发布时间】:2017-08-23 14:45:11
【问题描述】:

我需要在运行我的系统代码时记录大量数据。我可以使用哪些日志记录包来进行高效的异步日志记录? 默认情况下,标准 Python 日志记录包 (https://docs.python.org/2/library/logging.html) 是异步的吗?

【问题讨论】:

  • 不,不是。但是很容易编写自己的处理程序,将消息放入队列中,由其他线程拾取。
  • @KlausD。您能否解释更多或建议一些链接来阅读它?
  • 如果是linux可以直接使用syslog或者syslog-ng,使用起来很快。

标签: python python-2.7 asynchronous logging


【解决方案1】:

您可以使用 n 个 worker 池执行 logging.info() 消息,使用 concurrent.futures.ThreadPoolExecutor,n 应该始终等于一:

import concurrent.futures 
import logging

executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) 

def info(self, msg, *args):
    executor.submit(logging.info, msg, *args)

【讨论】:

  • 你能解释一下你的代码应该做什么以及它与我的问题有什么关系吗?
  • 代码示例显示,如何根据您的要求组织一种“info”函数调用的异步队列。在这里让工人数量等于一非常重要,这将为您提供准确的调用顺序。在 n 多于一个的情况下,您可能会出现意外行为 - 结果日志中的行顺序将是错误的。 BR,安德鲁
  • 请注意,如果您在调用info 后更改正在记录的值,则不确定将记录哪个版本。
【解决方案2】:

异步代码可以使用通常的日志记录功能,而无需借助特殊的异步模块或包装器。这样的代码是可能的。

import logging
        :

    async def do_some_async_stuff(self):
        logging.getLogger(__name__).info("Started doing stuff...")
        :
        logging.getLogger(__name__).warn("Things went awry...")

这里的问题是提交日志条目是否会在将条目写入文件时产生一些延迟,从而剥夺异步系统在此期间运行其他任务的机会。如果将写入文件的阻塞处理程序直接添加到日志层次结构的某处,则可能会发生这种情况。

标准logging 模块为此提供了一个简单的解决方案:使用非阻塞处理程序将其消息排入在其自己的私有线程中运行的所需阻塞处理程序。

撇开纯粹主义不谈,没有硬性规则阻止使用 QueueHandler 提供异步代码,该代码使用非阻塞日志处理程序进行记录,并与托管在 QueueListener 中的阻塞处理程序一起使用。

以下解决方案与调用 logging 记录器并以典型方式提交条目的协程完全兼容 - 不需要调用 .run_in_executor() 的包装器。异步代码不会遇到来自日志系统的任何阻塞行为。

例如,QueueHandler 可以设置为根处理程序

import queue
from logging.handlers import QueueHandler
    :
log_queue     = queue.Queue()
queue_handler = QueueHandler(log_queue)  # Non-blocking handler.

root = logging.getLogger()
root.addHandler(queue_handler)           # Attached to the root logger.

您想要的阻塞处理程序可以放在QueueListener 中:

from logging.handlers import QueueListener
from logging.handlers import RotatingFileHandler
    :
rot_handler    = RotatingFileHandler(...)   # The blocking handler.
queue_listener = QueueListener(log_queue, 
                               rot_handler) # Sitting comfortably in its
                                            # own thread, isolated from
                                            # async code.
queue_listener.start()

然后使用您需要的任何日志条目格式配置嵌套在侦听器中的处理程序。

我个人喜欢旋转文件处理程序,因为它限制了生成的日志文件的大小和数量,在创建新备份时删除最旧的文件。

【讨论】:

  • 对于一个完整的工作示例,您还需要从 logging.handlers 导入 QueueListener。
  • 你是对的,谢谢@TroyDaniels
猜你喜欢
  • 2015-07-14
  • 1970-01-01
  • 2011-10-23
  • 1970-01-01
  • 2019-03-05
  • 1970-01-01
  • 2020-12-31
  • 2018-02-28
  • 1970-01-01
相关资源
最近更新 更多