为什么在进程启动后添加时不使用python日志记录处理程序?

时间:2015-07-25 01:06:11

标签: python python-3.x logging

如果我正确解释了python3文档,无论我将处理程序添加到根记录器的哪个位置,都应该将Process中的日志消息发送到文件。但事实并非如此。

这是一个完整的程序,用于演示问题:

import logging
import logging.handlers

from multiprocessing import Process
from time import sleep

fileHandler = logging.FileHandler( 'mylog.log' )
fileHandler.setLevel( 5 )

logger = logging.getLogger( None )

def process_logger():

    print( "process waiting" )
    sleep( 5 )
    print( 'process start' )

    logger = logging.getLogger( None )

    for num in range( 1, 10 ):
        logger.critical( "critical: %d" % num )
        sleep(1)

#
# if this is where the handler is added, the critical messages
# will go to the file
#
logger.addHandler( fileHandler )

processLogger = Process( target=process_logger )
processLogger.start()

#
# if this is where the handler is added, the critical messages
# will not go to the file.
#
#logger.addHandler( fileHandler )

print( "started" )

我在OS X 10.10.4上使用python 3.4.3。

我猜测为什么这不起作用的是当我启动Process时,它会复制当前环境,如果到那时还没有添加处理程序,那么Process正在运行的环境中获胜#39有它。

我有三个问题:

  1. 为什么我的消息并不总是在文件中结束,无论我在哪里调用logger.addHandler?

  2. 我的邮件是否总是在文件中结束?

  3. 如果他们不应该,那么在Process启动后操作处理程序所需的一般问题的最佳解决方案是什么?

1 个答案:

答案 0 :(得分:3)

您看到的行为是由于进程如何在POSIX上运行。 POSIX上的多处理通常使用fork系统调用,当您通过Process(...)调用创建另一个进程时会发生这种情况。此时,创建的进程是原始进程的副本。在 Process(...)调用之前添加处理程序时,副本也已添加处理程序,因此process_logger(在副本中调用)将按预期运行。在Process(...)调用之后添加处理程序时,处理程序尚未添加到副本中,因此process_logger(在副本中调用)将不会按预期运行。

要避免此类问题,请确保在每个进程中根据需要配置日志记录(通常,这意味着在代码中执行日志记录配置(直接或间接)从{{ 1}} callable传递给target=XXX。就你的情况而言,Process

更新:有关将process_loggerlogging一起使用的详情,请参阅this post