Python多进程日志记录 - 为什么要使用multiprocessing.get_logger

19

我已经花了一段时间来解决多进程日志记录的问题,有很多原因。

其中之一就是为什么要使用另一个get_logger。

当然,我看过 这个问题 ,似乎multiprocessing.get_logger返回的记录器做了一些“进程共享锁”的魔法,使得日志处理变得平稳。

所以,今天我查看了Python 2.7的multiprocessing代码(/multiprocessing/util.py),发现这个记录器只是一个普通的logging.Logger,并且几乎没有任何魔法可言。

这是Python文档中get_logger函数前面的描述:

提供了一些日志记录支持。注意,logging包不使用进程共享锁,所以(根据处理程序类型)不同进程的消息可能会混合在一起。

所以,当您使用错误的日志记录处理程序时,即使是get_logger记录器也可能出错? 我已经使用了一个使用get_logger进行日志记录的程序很长时间了。 它将日志打印到StreamHandler中,看起来从未混淆过。

现在我的理论是:

  1. multiprocessing.get_logger不会执行进程共享锁
  2. StreamHandler适用于multiprocessing,但FileHandler不适用
  3. 此get_logger记录器的主要目的是跟踪进程的生命周期,并提供一个易于获取和准备好使用的记录器,已经记录了进程的名称/ID等信息

这里有个问题:

我的理论正确吗?

如何/为什么/何时使用这个get_logger?

2个回答

7
是的,我认为你说得对,multiprocessing.get_logger()不使用进程共享锁——正如你所说,文档中甚至明确说明了这一点。尽管有很多赞同,但看起来你所链接的问题陈述有误(让我们给它一个怀疑的余地,毕竟它是十多年前写的,所以也许曾经是这样)。
那么multiprocessing.get_logger()为什么存在呢?文档说它的作用是:
返回 multiprocessing 使用的记录器。如果需要,将创建新的记录器。
首次创建记录器时,其级别为 logging.NOTSET,没有默认处理程序。发送到此记录器的消息默认不会传播到根记录器。
也就是说,默认情况下multiprocessing模块不会产生任何日志输出,因为它的记录器的日志级别设置为NOTSET,因此不会生成任何日志消息。
如果您的代码出现问题,怀疑是与multiprocessing有关,则缺乏日志输出将无法帮助调试,这就是multiprocessing.get_logger()存在的原因——它返回multiprocessing模块本身使用的记录器,以便您可以覆盖默认的日志配置,从中获取一些日志并查看它正在做什么。
既然你要求如何使用multiprocessing.get_logger(),那么可以这样调用它,并像通常一样对记录器进行配置,例如:
logger = multiprocessing.get_logger()
formatter = logging.Formatter('[%(levelname)s/%(processName)s] %(message)s')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)

# now run your multiprocessing code

话虽如此,为了方便起见,您实际上可能需要使用multiprocessing.log_to_stderr(),根据文档

此函数执行对get_logger()的调用,但除了返回由get_logger创建的记录器之外,它还添加了一个处理程序,使用格式'[%(levelname)s/%(processName)s] %(message)s'将输出发送到sys.stderr

也就是说,它可以节省您设置大量日志配置的时间,您可以直接通过以下方式开始调试多进程问题:

logger = multiprocessing.log_to_stderr()
logger.setLevel(logging.INFO)

# now run your multiprocessing code

需要重申的是,这只是一个普通的模块记录器,正在被配置和使用,也就是说,它没有任何特别的或进程安全的功能。它只是让您看到多进程模块内部发生的情况。


因此,在您的答案中还要添加这一点,即multiprocessing.get_logger()不能用于跨多个进程进行日志记录!许多开发人员认为这种方法将为他们提供一个进程安全的日志记录功能,并且可以与FileHandler一起使用以在进程之间并发记录日志,因此他们期望类似于进程共享锁等内容。 - AmirHmZ
请澄清multiprocessing.get_logger()是一个普通的记录器,就像其他记录器一样!今天你可以看到许多模块提供可定制的日志功能,以查看模块内部发生的情况,因此multiprocessing.get_logger()返回的记录器就像它们一样。 - AmirHmZ
谢谢-我已经添加了一个结论段落来总结,以确保读者清楚。 - emmagordon

3

这篇答案并不是关于get_logger的,但也许你可以使用此帖子中建议的方法。请注意,QueueHandler/QueueListener类可通过logutils包(也可在PyPI上获得)在早期版本的Python中使用。


1
抱歉,我无法访问blobspot,因为我所在的地方无法访问。我知道你的帖子是关于多进程友好日志记录的,谢谢。关于这个问题,我实际上打算在我的项目中使用zmq.log,因为我的项目使用了zmq。 :-) - tdihp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接