来自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类的对象不能选择吗?(我在谷歌上搜索了一下,但什么也没找到)
发布于 2014-07-15 13:58:22
FileHandler对象内部使用一个threading.Lock来同步线程之间的写入。但是,不能对由thread.lock返回的threading.Lock对象进行腌制,这意味着不能在进程之间发送它,这是通过pool.map将其发送给子进程所必需的。
multiprocessing文档中有一节讨论如何使用multiprocessing进行这里日志记录。基本上,您需要让子进程继承父进程的记录器,而不是通过调用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.joininitializer/initargs用于在池的每个子进程启动后立即运行一次方法。在Linux上,由于os.fork的工作方式,这允许处理程序通过继承进入子处理程序。但是,这在Windows上是行不通的;由于缺乏对os.fork的支持,它仍然需要对handler进行筛选,才能通过initargs传递它。
https://stackoverflow.com/questions/24759779
复制相似问题