【问题标题】:Python multiprocessing - logging.FileHandler object raises PicklingErrorPython 多处理 - logging.FileHandler 对象引发 PicklingError
【发布时间】:2014-09-05 17:48:01
【问题描述】:

似乎来自logging 模块和multiprocessing 作业的处理程序不会混合:

import functools
import logging
import multiprocessing as mp

logger = logging.getLogger( 'myLogger' )
handler = logging.FileHandler( 'logFile' )

def worker( x, handler ) :
    print x ** 2

pWorker = functools.partial( worker, handler=handler )

#
if __name__ == '__main__' :
    pool = mp.Pool( processes=1 )
    pool.map( pWorker, range(3) )
    pool.close()
    pool.join()

输出:

cPickle.PicklingError: Can't pickle <type 'thread.lock'>: attribute lookup thread.lock failed

如果我将pWorker替换为以下任一方法,则不会引发错误

# this works
def pWorker( x ) :
    worker( x, handler )

# this works too
pWorker = functools.partial( worker, handler=open( 'logFile' ) )

我不太了解PicklingError。是因为logging.FileHandler 类的对象不可挑选吗? (我用谷歌搜索但没有找到任何东西)

【问题讨论】:

    标签: python python-2.7 multiprocessing pickle


    【解决方案1】:

    FileHandler 对象在内部使用threading.Lock 来同步线程之间的写入。但是threading.Lock返回的thread.lock对象不能pickle,也就是说不能在进程间发送,需要通过pool.map发送给child。

    multiprocessing 文档中有一个部分讨论了使用multiprocessing 进行日志记录的工作原理here。基本上,您需要让子进程继承父进程的记录器,而不是尝试通过调用 map 显式传递记录器或处理程序。

    但请注意,在 Linux 上,您可以这样做:

    from multiprocessing import Pool
    import logging
    
    logger = logging.getLogger( 'myLogger' )
    
    
    def worker(x):
        print handler
        print x **2 
    
    def initializer(handle):
        global handler
        handler = handle
    
    if __name__ == "__main__":
        handler = logging.FileHandler( 'logFile' )
        #pWorker = functools.partial( worker, handler=handler )
        pool = Pool(processes=4, initializer=initializer, initargs=(handler,))
        pool.map(worker, range(3))
        pool.close()
        pool.join
    

    initializer/initargs 用于在池的每个子进程启动后立即运行一次方法。在 Linux 上,由于os.fork 的工作方式,这允许处理程序通过继承进入子进程。但是,this won't work on Windows;因为它缺乏对os.fork 的支持,它仍然需要腌制handler 以通过initargs 传递它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-13
      • 1970-01-01
      • 2012-02-06
      • 2011-10-24
      • 1970-01-01
      • 2017-03-07
      • 2015-09-27
      相关资源
      最近更新 更多