Python 3:多处理线程池中的线程终止不起作用
Python 3: Termination of threads in multiprocessing ThreadPool not working
我正在使用 Ubuntu 16.04.2 LTS 和 Python 3.5.2。
我有一个来自 multiprocessing
的 ThreadPool
在做一些工作。
现在我想在工作时终止这个池。
使用 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
(取模通常的注意事项关于搞砸通信队列)。
我正在使用 Ubuntu 16.04.2 LTS 和 Python 3.5.2。
我有一个来自 multiprocessing
的 ThreadPool
在做一些工作。
现在我想在工作时终止这个池。
使用 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
(取模通常的注意事项关于搞砸通信队列)。