没有任何过程能在不使用像 os.kill()
这样的暴力手段的情况下阻止另一个进程。别去那里。
要理智地完成这个任务,你需要重新构思你的基本方法:主进程和工作进程需要相互通信。
我会详细说明,但目前的示例太简单了,没什么用处。例如,按照目前的写法,只调用了 rand()
不超过 num_workers
次,因此没有理由认为其中任何一次必须大于 0.7。
一旦工作函数增加了循环,就变得更加明显了。例如,工作进程可以在循环的顶部检查是否设置了一个 mp.Event
,如果设置了,就退出。主进程将在希望工作进程停止时设置该事件。
当一个工作进程找到一个值大于 0.7 时,它可以设置一个不同的 mp.Event
。主进程将等待该事件,然后设置 "停止时间" 的 Event
,以供工作进程查看,然后做常规循环,使用 .join()
关闭工作线程。
编辑
以下是一个具备可移植性和清晰性的完整解决方案,假设工作进程将一直运行,直到至少有一个找到大于 0.7 的值。注意,我从中删除了 numpy
,因为它与此代码无关。这里的代码应该在支持 multiprocessing
的任何平台上的标准 Python 下正常工作:
import random
from time import sleep
def worker(i, quit, foundit):
print "%d started" % i
while not quit.is_set():
x = random.random()
if x > 0.7:
print '%d found %g' % (i, x)
foundit.set()
break
sleep(0.1)
print "%d is done" % i
if __name__ == "__main__":
import multiprocessing as mp
quit = mp.Event()
foundit = mp.Event()
for i in range(mp.cpu_count()):
p = mp.Process(target=worker, args=(i, quit, foundit))
p.start()
foundit.wait()
quit.set()
还有一些示例输出:
0 started
1 started
2 started
2 found 0.922803
2 is done
3 started
3 is done
4 started
4 is done
5 started
5 is done
6 started
6 is done
7 started
7 is done
0 is done
1 is done
所有的东西都能够干净地关闭:没有追踪,没有异常终止,没有残留的僵尸进程……就像吹口哨一样干净。
结束它
正如@noxdafox所指出的那样,有一个Pool.terminate()
方法,它可以尽最大努力跨平台杀死工作进程,无论它们正在做什么(例如,在Windows上,它调用平台的TerminateProcess()
)。我不建议在生产代码中使用它,因为突然终止进程可能会使各种共享资源处于不一致的状态,或者让它们泄漏。在multiprocessing
文档中有各种警告,您应该将其添加到您的操作系统文档中。
不过,这可能是方便的!以下是使用此方法的完整程序。请注意,我将截止值提高到了0.95,以使其更可能需要花费比眨眼更长的时间才能运行:
import random
from time import sleep
def worker(i):
print "%d started" % i
while True:
x = random.random()
print '%d found %g' % (i, x)
if x > 0.95:
return x
sleep(0.5)
def quit(arg):
print "quitting with %g" % arg
p.terminate()
if __name__ == "__main__":
import multiprocessing as mp
ncpu = mp.cpu_count()
p = mp.Pool(ncpu)
for i in range(ncpu):
p.apply_async(worker, args=(i,), callback=quit)
p.close()
p.join()
还有一些示例输出:
$ python mptest.py
0 started
0 found 0.391351
1 started
1 found 0.767374
2 started
2 found 0.110969
3 started
3 found 0.611442
4 started
4 found 0.790782
5 started
5 found 0.554611
6 started
6 found 0.0483844
7 started
7 found 0.862496
0 found 0.27175
1 found 0.0398836
2 found 0.884015
3 found 0.988702
quitting with 0.988702
4 found 0.909178
5 found 0.336805
6 found 0.961192
7 found 0.912875
$ [the program ended]