我目前正在使用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'])
但是,现在我不确定如何监视线程是否仍处于活动状态,我正在寻找这样,以便我可以重新启动由于某种原因崩溃的线程。有什么建议吗?
答案 0 :(得分:5)
我是pathos
和dill
作者。 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"