Python 3:多处理线程池中的线程终止不起作用

Python 3: Termination of threads in multiprocessing ThreadPool not working

我正在使用 Ubuntu 16.04.2 LTS 和 Python 3.5.2。 我有一个来自 multiprocessingThreadPool 在做一些工作。 现在我想在工作时终止这个池。

使用 ThreadPool.terminate() 没有按预期工作。 当 运行 以下示例时,worker 永远不会停止工作,并且程序永远不会运行到 ThreadPool.join() 调用之后。

import time
from multiprocessing.pool import ThreadPool

def task():
    try:
        while True:
            print("Working")
            time.sleep(1)
    except: # Unsuccessful attempt. :(
        print("Working, stopping now")

thread_pool = ThreadPool(processes=1)

thread_pool.apply_async(task)
time.sleep(1) # Make sure the task is actually started.

print("Terminating")
thread_pool.terminate()
print("Termination: Initiated")
thread_pool.join() # Does not return.
print("Termination: Done")

我做错了什么?

您特别要求 ThreadPool 而不是 Pool。这意味着 multiprocessing 代码将创建一个本地线程(在您自己的进程中),而不是创建一个新进程。

A ThreadPool 实例不能突然终止,因为没有为此定义的机制(相对于系统可以调用 os.kill 的进程)。在您的代码中, .terminate 指令最终被忽略。事实上,它设置了一个标志,池实例将在任务 returns 时检查,但你的任务永远不会 returns。我们可以在修改后的版本中看到这一点:

import argparse
import sys
import time

from multiprocessing.pool import Pool, ThreadPool

def task(arg):
    for i in range(3):
        print("Working on", arg, "with i =", i)
        time.sleep(1)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--delay', default=1, type=float)
    args = parser.parse_args()

    thread_pool = ThreadPool(processes=1)

    thread_pool.apply_async(task, (0,))
    thread_pool.apply_async(task, (1,))
    time.sleep(args.delay)

    print("Terminating")
    thread_pool.terminate()
    print("Termination: Initiated")
    thread_pool.join() # Does not return.
    print("Termination: Done")

if __name__ == '__main__':
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        sys.exit('\nInterrupted')

当 运行 没有参数时执行此操作:

$ python3 tp.py
Working on 0 with i = 0
Working on 0 with i = 1
Terminating
Termination: Initiated
Working on 0 with i = 2
Termination: Done

当 运行 和 --delay 5 时:

$ python3 tp.py --delay 5
Working on 0 with i = 0
Working on 0 with i = 1
Working on 0 with i = 2
Working on 1 with i = 0
Working on 1 with i = 1
Terminating
Working on 1 with i = 2
Termination: Initiated
Termination: Done

或者,如果您只使用 Pool 而不是 ThreadPool,您将获得一个真实的进程,并且可以随时在其上使用 .terminate(取模通常的注意事项关于搞砸通信队列)。