2012-04-05 48 views
2

我最近面臨着將多進程操作納入我們的軟件的挑戰。我想要一個主進程產生子進程,並且我需要一些將日誌信息發送回主進程的方式。這主要是因爲我們使用的模塊將警告和錯誤消息寫入日誌記錄對象,我們希望這些消息出現在主進程中運行的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://stackoverflow.com/a/9823098/1132524),我寫的不是很久以前,很有用。 – 2012-04-05 13:16:50

+0

感謝這個Rik,這也有幫助。 – 2012-04-05 13:23:15

回答

3

你的問題是與日誌模塊的配置:

你需要調用log.setLevel(logging.INFO)。默認日誌級別爲WARNING,因此您的日誌不起作用。

您確實在處理程序對象上調用了setLevel,但記錄的消息從未到達處理程序,因爲它們被記錄程序過濾。處理程序本身不需要調用setLevel,因爲它默認處理所有消息。

+0

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

相關問題