2014-07-19 27 views
1

所以我試圖在multiprocessing上下文中使用logging。假設我想讓每個進程寫入自己的日誌文件。這裏是我的設置:在多處理上下文中混淆Python日誌記錄模塊的行爲

# worker.py 
import logging 
import os 

def worker(x) : 
    """ 
    Write the value of x in the log file 
    """ 
    logger = logging.getLogger(__name__) 
    pid = os.getpid() # get the process id 
    handler = logging.FileHandler(str(pid) + ".log") 
    logger.addHandler(handler) 
    logger.info("pid={pid}, x={x}".format(**locals())) 

這是我main

import logging 
import multiprocessing as mp 
import worker 

# logger 
logger = logging.getLogger() 
logger.setLevel(logging.INFO) 

# handler 
handler = logging.FileHandler('main.log') 
logger.addHandler(handler) 

# 
if __name__ == '__main__' : 
    pool = mp.Pool(processes=2) 
    pool.map(worker.worker, range(5)) 
    pool.close() 
    pool.join() 

現在輸出的日誌文件。這是main.log

pid=1985, x=0 
pid=1985, x=2 
pid=1986, x=1 
pid=1985, x=3 
pid=1986, x=4 

我覺得這個輸出是否正常:兩個子進程的事件傳播到根父。所以它不是對應於Logging to a single file from multiple processes的情況(是嗎?)。但現在這裏是第一子進程日誌文件:

pid=1985, x=0 
pid=1985, x=2 
pid=1985, x=2 
pid=1985, x=3 
pid=1985, x=3 
pid=1985, x=3 

這是第二個孩子的日誌文件:

pid=1986, x=1 
pid=1986, x=4 
pid=1986, x=4 

它看起來像每個子進程的第一次輸入寫入日誌,兩次第二次,第三次三次等等。發生什麼事了?

回答

4

發生這種情況的原因是,每次輸入worker時,都會獲得對同一個logger對象的引用,然後向其添加新的FileHandler。所以如果worker被稱爲三次,它的logger最終有三個FileHandlers,它們都碰巧寫入同一個文件。您應該使用initializer關鍵字參數在啓動時設置在每個Pool過程中記錄一次:

def init() : 
    logger = logging.getLogger(__name__) 
    pid = os.getpid() # get the process id 
    handler = logging.FileHandler(str(pid) + ".log") 
    logger.addHandler(handler) 

然後開始喜歡這張

p = multiprocessing.Pool(processes=2, initializer=init) 

然後工人可以只搶logger對象和使用它沒有增加一個FileHandler它。

相關問題