使用PYTHON的多处理池和映射功能进行键盘中断
问题描述
我找到了this文章,介绍了如何使用Ctrl+c终止正在运行的多进程代码。以下代码完全正常(可以使用Ctrl+c终止它):
#!/usr/bin/env python
# Copyright (c) 2011 John Reese
# Licensed under the MIT License
import multiprocessing
import os
import signal
import time
def init_worker():
signal.signal(signal.SIGINT, signal.SIG_IGN)
def run_worker():
time.sleep(15)
def main():
print "Initializng 5 workers"
pool = multiprocessing.Pool(5, init_worker)
print "Starting 3 jobs of 15 seconds each"
for i in range(3):
pool.apply_async(run_worker)
try:
print "Waiting 10 seconds"
time.sleep(10)
except KeyboardInterrupt:
print "Caught KeyboardInterrupt, terminating workers"
pool.terminate()
pool.join()
else:
print "Quitting normally"
pool.close()
pool.join()
if __name__ == "__main__":
main()
问题是我使用多处理模块中的不同函数。我不知道它们与以前的方法有什么不同,它只对我有效(除了这个例子不能使用ctrl+c终止它)。以下是我一直试图根据上面的版本修改的代码(以前的版本没有信号处理,用于在按下ctrl+c时打印回溯):
#!/usr/bin/env python
from time import sleep
import signal
from multiprocessing import Pool
from multiprocessing import cpu_count
def init_worker(n):
signal.signal(signal.SIGINT, signal.SIG_IGN)
sleep(.5)
print "n = %d" % n
results_sent_back_to_parent = n * n
return results_sent_back_to_parent
if __name__ == '__main__':
try:
p = Pool(processes = cpu_count())
results = p.map(init_worker, range(50), chunksize = 10)
except KeyboardInterrupt:
pool.terminate()
pool.join()
print(results)
问题:
- 为什么ctrl+c在第一个示例中起作用,而在第二个示例中不起作用
- 如何修改ctrl+c将起作用的第二个代码?
- 这两个代码有什么不同(我的意思是在多处理环境中,一个使用
pool.apply_async
,另一个使用map
)?
编辑
回复@user2386841
我已在init_worker
中添加了signal.signal(signal.SIGINT, signal.SIG_IGN)
,并尝试在if __name__ == '__main__':
之后添加,但id不起作用,与我将其添加为try:
块中的最后一行时相同
回复@ThomasWagenaar
它的行为完全相同(我也尝试了上面提到的信号处理程序的不同位置);尽管点击ctr+c
,数字仍在打印,唯一可能的终止脚本的方法是使用ctrl+z
将其发送到后台,然后使用kill %1
解决方案
我用这个简单的函数解决了这个问题:
import os
import psutil
import signal
parent_id = os.getpid()
def worker_init():
def sig_int(signal_num, frame):
print('signal: %s' % signal_num)
parent = psutil.Process(parent_id)
for child in parent.children():
if child.pid != os.getpid():
print("killing child: %s" % child.pid)
child.kill()
print("killing parent: %s" % parent_id)
parent.kill()
print("suicide: %s" % os.getpid())
psutil.Process(os.getpid()).kill()
signal.signal(signal.SIGINT, sig_int)
我已将其附加到我的池:
Pool(3, worker_init)
ctrl^c后的结果为:
^Csignal: 2
signal: 2
signal: 2
killing child: 14109
killing child: 14110
killing parent: 14104
suicide: 14108
Killed
然后一切都退出
相关文章