如果我正确解释了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有它。
我有三个问题:
为什么我的消息并不总是在文件中结束,无论我在哪里调用logger.addHandler?
我的邮件是否总是在文件中结束?
如果他们不应该,那么在Process启动后操作处理程序所需的一般问题的最佳解决方案是什么?
答案 0 :(得分:3)
您看到的行为是由于进程如何在POSIX上运行。 POSIX上的多处理通常使用fork系统调用,当您通过Process(...)
调用创建另一个进程时会发生这种情况。此时,创建的进程是原始进程的副本。在 Process(...)
调用之前添加处理程序时,副本也已添加处理程序,因此process_logger
(在副本中调用)将按预期运行。在Process(...)
调用之后添加处理程序时,处理程序尚未添加到副本中,因此process_logger
(在副本中调用)将不会按预期运行。
要避免此类问题,请确保在每个进程中根据需要配置日志记录(通常,这意味着在代码中执行日志记录配置(直接或间接)从{{ 1}} callable传递给target=XXX
。就你的情况而言,Process
。
更新:有关将process_logger
与logging
一起使用的详情,请参阅this post。