杀死Python多处理池

时间:2014-08-20 21:57:00

标签: python linux multiprocessing

我正在运行一个Python程序,它使用多处理模块来生成一些工作线程。使用Pool.map这些消化文件列表。

在某些时候,我想停止一切并让脚本死掉。

通常命令行中的Ctrl+C可以完成此操作。但是,在这种情况下,我认为只会中断其中一名工人,并产生一名新工人。

因此,我最终在有问题的流程ID上运行ps aux | grep -i python并使用kill -9

是否有更好的方法让中断信号使一切停止?

4 个答案:

答案 0 :(得分:22)

SIGQUIT( Ctrl + \ )即使在Python 2.x下也会终止所有进程。

你也可以更新到Python 3.x,这种行为(只有孩子获得信号)似乎已得到修复。

答案 1 :(得分:4)

不幸的是,在Python 2.x中,对于这个问题确实没有一个好的解决方案。我所知道的最佳解决方法是使用pool.map_async(...).get(timeout=<large number>)而不是pool.map。问题是pool.map调用threading.Condition.wait(),由于某种原因,它不能被Python 2.x中的Ctrl + C中断(它在Python 3中有效)。当您使用map_async()时,它会调用threading.Condition.wait(timeout=<large number>),最终会执行忙等待循环,可以被Ctrl + C中断。

亲自试试:

c = threading.Condition()
try:
    c.acquire()
    c.wait()  # You won't be able to interrupt this
except KeyboardInterrupt:
    print("Caught it")

c = threading.Condition()
try:
    c.acquire()
    c.wait(timeout=100)  # You CAN interrupt this
except KeyboardInterrupt:
    print("Caught it")

因此,要使map来电中断,请执行以下操作:

if __name__ == "__main__":
    p = multiprocessing.Pool()
    try:
        p.map_async(func, iterable).get(timeout=10000000)
    except KeyboardInterrupt:
        print("Caught it")
        # Optionally try to gracefully shut down the worker processes here.
        p.close()
        # DON'T join the pool. You'll end up hanging.

另请注意,正如phihag所指出的,这个问题在Python 3.4中得到修复(可能在3.x中更早)。

答案 2 :(得分:3)

有两种方法。第一种方法是使用

将线程标记为守护进程

在线程中,

myThread.setDaemon(true)
多处理中的

myThread.daemon = True

标记为守护程序的所有线程将以主线程终止。这不是正确的方法,因为它不允许线程清理

下一个方法是使用try-catch监听KeyboardInterrupt,然后使用.join()这样的线程。

try:
    myThread = MyThread()
except KeyboardInterrupt:
    myThread.join()

如果您的线程处于循环中,您可以使用诸如boolean的条件,将其设置为false,并且当条件为false时,它将执行清理。

class MyThread(Threading.thread):
    def __init__(self):
        self.alive=True
    def run(self):
        while self.alive:
            #do stuff
        #cleanup goes here, outside the loop
try:
    myThread = MyThread()
except KeyboardInterrupt:
    myThread.alive = False
    myThread.join()

答案 3 :(得分:0)

我发现在这种情况下使用python信号库效果很好。初始化池时,可以将信号处理程序传递给每个线程,以便在主线程获得键盘中断时设置默认行为。

如果你真的只想让一切都死掉,赶上主线程中的键盘中断异常,并调用pool.terminate()。