多处理 - > pathos.multiprocessing和windows

时间:2015-07-30 20:02:14

标签: python multiprocessing pickle dill pathos

我目前正在使用python中的标准多处理来生成一系列无限期运行的进程。我并不特别关心表现;每个线程只是在观察文件系统上的不同更改,并在修改文件时采取适当的操作。

目前,我有一个解决方案,可以满足我的需求,适用于Linux。我有一个函数和参数的字典,如下所示:

 job_dict['func1'] = {'target': func1, 'args': (args,)}

对于每一个,我创建一个过程:

 import multiprocessing
 for k in job_dict.keys():
     jobs[k] = multiprocessing.Process(target=job_dict[k]['target'],
                                       args=job_dict[k]['args'])

有了这个,我可以跟踪每个正在运行的,并在必要时重新启动因任何原因崩溃的作业。

这在Windows中不起作用。我正在使用的许多函数都是包装器,使用各种functools函数,我得到的消息是无法序列化函数(参见What can multiprocessing and dill do together?)。我还没弄清楚为什么我在Linux中没有出现这个错误,但在Windows中也是如此。

如果我在Windows中启动进程之前导入dill,则不会出现序列化错误。但是,这些过程实际上并没有做任何事情。我无法弄清楚为什么。

然后我切换到pathos中的多处理实现,但没有找到标准Process模块中的简单multiprocessing类的模拟。我能够使用pathos.pools.ThreadPool为每个作业生成线程。这不是map的预期用途,我敢肯定,但它启动了所有线程,并且它们在Windows中运行:

import pathos
tp = pathos.pools.ThreadPool()
for k in job_dict.keys():
    tp.uimap(job_dict[k]['target'], job_dict[k]['args'])

但是,现在我不确定如何监视线程​​是否仍处于活动状态,我正在寻找这样,以便我可以重新启动由于某种原因崩溃的线程。有什么建议吗?

1 个答案:

答案 0 :(得分:5)

我是pathosdill作者。 Process类深埋在pathos pathos.helpers.mp.process.Process内,其中mp本身就是multiprocessing库的实际分支。 multiprocessing中的所有内容都应该可以从那里访问。

关于pathos的另一件事是,它会让pool保持活着,直到你从保持状态中移除它为止。这有助于减少创建“新”池的开销。要删除池,请执行以下操作:

>>> # create
>>> p = pathos.pools.ProcessPool()
>>> # remove
>>> p.clear()

然而,Process没有这样的机制。

对于multiprocessing,Windows与Linux和Macintosh不同...因为Windows在Linux上没有合适的fork ... linux可以跨进程共享对象,而在Windows上没有共享...它基本上是一个完全独立的新进程...因此序列化必须更好地让对象传递到另一个进程 - 就像你将对象发送到另一台计算机一样。在Linux上,你必须这样做以获得相同的行为:

def check(obj, *args, **kwds):
    """check pickling of an object across another process"""
    import subprocess
    fail = True
    try:
        _x = dill.dumps(x, *args, **kwds)
        fail = False
    finally:
        if fail:
            print "DUMP FAILED"
    msg = "python -c import dill; print dill.loads(%s)" % repr(_x)
    print "SUCCESS" if not subprocess.call(msg.split(None,2)) else "LOAD FAILED"