Python 多进程池 信号
我遇到了一个小问题,我是Python中多进程模块的初学者,我需要创建一个可以随时通过SIGINT信号停止的进程池。
from multiprocessing import Pool, current_process
import signal
import time
import os
class Processor(object):
def __init__(self, stack):
self.stack = stack
self.pool = Pool(processes=4, maxtasksperchild=1, initializer=self._init)
def _init(self):
cp = current_process()
cp.daemon = False
def launch(self):
self.result = self.pool.map(func, self.stack)
self.pool.close()
self.pool.join()
def func(j):
a, b = j
time.sleep(1)
return a * b
def breaker(*args):
p.pool.terminate()
p.pool.join()
def main():
a = 4, 9
b = 5, 7
lst = [a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b, a, b]
global p
p = Processor(lst)
signal.signal(signal.SIGINT, breaker)
p.launch()
ret = p.result
for i in ret:
print i
if __name__ == '__main__':
print os.getpid()
main()
没有任何信号的时候,代码运行得很好,但当我给这个进程发送信号时,它就不再工作了,停止的函数也从来没有被调用过。如果有人知道为什么,请告诉我。
1 个回答
0
当你调用了breaker函数时,它确实会被执行,但它并不会告诉主程序要退出。如果你在最后加上:
sys.exit(os.EX_OK)
或者在breaker的最后加上其他的退出指令,这样程序就会真正退出。
另外,你可能想把这个:
signal.signal(signal.SIGINT, breaker)
放在Pool定义之前,这样可以防止在子进程中出现未处理的键盘中断。
如果你想获取部分结果,可以尝试以下方法...
你的启动代码需要改成:
# start the workers
for el in self.stack:
self.result[el] = self.pool.apply_async(func, (el, ), callback=your_callback)
#wait for results
for work in self.result.items(): # or iteritems if you're on pre python3
work[1].get()
self.pool.close()
self.pool.join()
这样做会让结果一个一个地以异步调用的方式返回,你的回调函数就有机会把结果保存到某个地方,以便后续使用。
而使用map的话,它只会在最后一次调用时返回结果,所以你无法获取到部分结果。
接下来,你需要在某个地方定义your_callback,这样它就能把结果写入到一个全局的结果列表中:
def your_callback(result):
global_list.append(result)
不过,结果的顺序可能会有些乱...
现在你的结果会一个一个地存放在global_list中,你可以在main()或者breaker()中输出这些结果。