使用SIGINT取消多处理.Pool

时间:2018-05-08 10:33:54

标签: python python-3.x signals python-multiprocessing

我的目标是并行计算多个数据点,并将它们异步写入IO设备。数据点不能只由它们自己编写,而是需要包装;更确切地说,我正在编写一个JSON数组,并且需要在结构周围添加[]符号。

我目前的方法是使用multiprocessing.Pool和apply_async来计算数据点。使用回调函数,然后将数据点发送到multiprocessing.Queue,同时单独的线程同步从队列中提取元素并将它们写入IO设备。

我可能需要使用SIGINT取消进程。在这种情况下,我希望计算安全地完成,即停止计算所有Pool进程,但完成编写队列中的所有剩余元素和]符号。

到目前为止,我没有找到解决问题的有效方法。在目前的状态,我的两个问题是:

  • 有时,流程不会退出。调用SIGINT_handler但该进程不会终止。我无法验证它的来源,但我认为它可能是队列中的死锁?我不知道如何防止这种情况。
  • 据我了解,pool.terminate()向其所有子进程发送SIGTERM。这显然会在每一个中引起KeyboardInterrupt异常,使十二个堆栈跟踪混乱终端。

我的代码可以在下面找到。

# Initialize the worker pool and necessary variables.
pool = multiprocessing.Pool(os.cpu_count() - 1)
data_queue = multiprocessing.Queue()
counter_lock = threading.Lock()
threads_todo = args.autnum

# This function is executed after each successful experiment.
def apply_finished(data):
    data_queue.put(data)
    with counter_lock:
        nonlocal threads_todo
        threads_todo -= 1

# Start the pool.
for i in range(args.autnum):
    pool.apply_async(collect_data, (args,), callback=apply_finished)
pool.close()

# This function is called if SIGINT is send to this process.
def SIGINT_handler(sig, frame):
    sys.stderr.write("SIGINT received. Cancelling...")
    sys.stderr.flush()
    pool.terminate()
    with counter_lock:
        nonlocal threads_todo
        threads_todo = 0
signal.signal(signal.SIGINT, SIGINT_handler)

# Write the data to stdout until all workers terminate or a SIGINT is received.
sys.stdout.write("[\n")
while threads_todo > 0 or not data_queue.empty():
    try:
        data = data_queue.get(True, 1)
        s = data.decode('utf-8')
        sys.stdout.write(s)
        sys.stdout.flush()
    except queue.Empty:
        data = None
sys.stdout.write("]")

0 个答案:

没有答案