Python 3:使用多处理队列进行日志记录

问题描述:

我最近面临着将多进程操作纳入我们的软件的挑战。我想要一个主进程产生子进程,并且我需要一些将日志信息发送回主进程的方式。这主要是因为我们使用的模块将警告和错误消息写入日志记录对象,我们希望这些消息出现在主进程中运行的gui中。Python 3:使用多处理队列进行日志记录

明显的方法是用write()方法编写一个小类,将write()放入队列中,然后在日志流处理程序中使用此类。然后主进程从这个队列中获取()将文本发送给gui。但这似乎没有工作,我不知道为什么

我写了一些示例代码来演示问题。它使用日志记录对象在子进程中写入队列,然后主进程尝试从队列中读取,但失败。有人能帮我弄清楚这有什么问题吗?

import time, multiprocessing, queue, logging 

class FileLikeQueue: 
    """A file-like object that writes to a queue""" 
    def __init__(self, q): 
     self.q = q 
    def write(self, t): 
     self.q.put(t) 
    def flush(self): 
     pass 


def func(q): 
    """This function just writes the time every second for five 
    seconds and then returns. The time is sent to the queue and 
    to a logging object""" 

    stream = FileLikeQueue(q) 

    log = logging.getLogger() 
    infohandler = logging.StreamHandler(stream) 
    infohandler.setLevel(logging.INFO) 
    infoformatter = logging.Formatter("%(message)s") 
    infohandler.setFormatter(infoformatter) 
    log.addHandler(infohandler) 

    t1 = time.time() 
    while time.time() - t1 < 5: #run for five seconds 
     log.info('Logging: ' + str(time.time())) 
     q.put('Put: %s' % str(time.time())) 
     time.sleep(1) 



def main(): 
    q = multiprocessing.Queue() 
    p = multiprocessing.Process(target=func, args=(q,)) 
    p.start() 

    #read the queue until it is empty 
    while True: 
     try: 
      t = q.get() 
     except queue.Empty: 
      break 
     print(t) 


if __name__ == '__main__': 
    main() 

我期望的输出是:

Logging: 1333629221.01 
Put: 1333629221.01 
Logging: 1333629222.02 
Put: 1333629222.02 
Logging: 1333629223.02 
Put: 1333629223.02 
Logging: 1333629224.02 
Put: 1333629224.02 
Logging: 1333629225.02 
Put: 1333629225.02 

但我得到的是:

Put: 1333629221.01 
Put: 1333629222.02 
Put: 1333629223.02 
Put: 1333629224.02 
Put: 1333629225.02 

所以认沽()在FUNC操作()的作品,但记录没有按“T。为什么?

谢谢。

+1

我没有深入你的代码,但如果你正在尝试登录多路处理环境,你可能会发现[这个答案](http://*.com/a/9823098/1132524),我写的不是很久以前,很有用。 – 2012-04-05 13:16:50

+0

感谢这个Rik,这也有帮助。 – 2012-04-05 13:23:15

你的问题是与日志模块的配置:

你需要调用log.setLevel(logging.INFO)。默认日志级别为WARNING,因此您的日志不起作用。

您确实在处理程序对象上调用了setLevel,但记录的消息从未到达处理程序,因为它们被记录程序过滤。处理程序本身不需要调用setLevel,因为它默认处理所有消息。

+0

你是对的!对不起,我以前没有看到。 – 2012-04-05 13:22:20