我的代码如下,
class _Process(multiprocessing.Process):
STOP = multiprocessing.Manager().Event()
def __init__(self, queue, process_fn):
self._q = queue
self._p = process_fn
super().__init__()
def run(self):
while True:
dat = self._q.get()
if not dat is _Process.STOP:
self._p(dat, self._q)
self._q.task_done()
else:
self._q.task_done()
break
但是,我无法成功比较STOP
。当我使用is
时,这并不奇怪,因为我相信is
比较对象ID和文档“......这是对象在内存中的地址。 “因此,由于我使用多个进程,因此内存地址会有所不同。 (我无法将它与==
进行比较,但我不确定为什么会这样。)
我使用Manager()
创建的任何对象都会发生这种情况,但如果我使用“true”单例(True
或False
或None
),则确实有效。虽然这不是一个合适的解决方案,因为这些值中的任何一个都可能在队列中有效。
那么如何创建一个可以跨进程进行比较的变量(如单例)?
(N.B。我也试过使用专门的课程,但是因为它无法被腌制而得到错误。)
更新:答案似乎是使用一个类,但我收到了挑剔的问题,因为我只是尝试使用内部类。将其移动到模块范围可以修复错误并且工作正常。 - 谢谢@Schnouki!
以下是代码的示例(并且无意义)用法,显示错误...
def f(data, queue):
print(data)
q = multiprocessing.JoinableQueue()
for i in range(4):
p = _Process(q, f)
p.daemon = True
p.start()
q.put(i)
q.join()
for i in range(4):
q.put(_Process.STOP)
q.join()
答案 0 :(得分:3)
使用Event
对象这是一种奇怪的方式...如果你不能使用None
或布尔值,我建议你使用一个专用的类来测试你得到的类型从队列中:
class StopProcessing(object):
pass
#...
q.put(StopProcessing())
#...
while True:
dat = self._q.get()
if type(dat) is StopProcessing:
# ...
或者,当然,您可以继续使用multiprocessing.Event
并测试其类型。但是,如果其他人阅读您的代码,这可能会产生误导;使用专用类型对我来说似乎更清洁和Pythonic。
编辑:好的,显然这不起作用,因为新类不可选。所以这是另一个想法:如果直接将类型放入队列中,如下所示:
class StopProcessing(object):
pass
#...
q.put(StopProcessing)
#...
while True:
dat = self._q.get()
if dat is StopProcessing:
#...
根据pickle doc,“模块顶层定义的类”可以被腌制。