【问题标题】:python multiprocessing pool signalpython多处理池信号
【发布时间】:2014-08-12 09:14:07
【问题描述】:

我遇到了一个小问题,我是 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()

在没有任何信号的情况下,代码可以完美执行,但是当我向该进程发送信号时,它不再起作用,并且永远不会调用中断函数。 如果有人知道为什么。

【问题讨论】:

    标签: python signals multiprocessing pool


    【解决方案1】:

    breaker 函数确实被调用,但它不会告诉你的 main 退出,如果你添加:

    sys.exit(os.EX_OK)
    

    或任何其他在断路器结束时的出口,那么它将实际退出。

    你也可以移动这个:

    signal.signal(signal.SIGINT, breaker)
    

    在池定义之前应该停止子进程中未处理的键盘中断

    要获得部分结果,您可能需要执行以下操作...

    你的发布必须变成:

    # 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() 或 break() 中输出它

    【讨论】:

    • 您的解决方案完美运行,但我还有另一个上面没有提到的问题。我怎么能得到 map 的结果,因为我在他跑步期间阻止了他,但他可能已经完成了一些任务,直到我发送 SIGINT。而我无法得到它们。你知道为什么吗?
    • 我担心检索部分结果会有更多问题......地图可能不是你想要使用的,我可以发布一些代码,一分钟内就能做到这一点
    • 非常感谢您的帮助。我不再使用地图,我现在正在使用 apply_async,您的解决方案非常有效,非常感谢您
    猜你喜欢
    • 1970-01-01
    • 2021-07-24
    • 2020-08-14
    • 2016-11-10
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    相关资源
    最近更新 更多