`concurrent.futures` 中 `with` 的作用是什么?

6
下面的代码按预期执行,几乎立即返回总完成时间,因为它不等待线程完成每个任务。
import concurrent.futures
import time

start = time.perf_counter()


def do_something(seconds):
    print(f'Sleeping {seconds} second(s)...')
    time.sleep(seconds)
    return f'Done Sleeping...{seconds}'



executor= concurrent.futures.ThreadPoolExecutor()
secs = [10, 4, 3, 2, 1]

fs = [executor.submit(do_something, sec) for sec in secs]


finish = time.perf_counter()

print(f'Finished in {round(finish-start, 2)} second(s)')

但是使用with命令会等待:

with concurrent.futures.ThreadPoolExecutor() as executor:
    secs = [10, 4, 3, 2, 1]

    fs = [executor.submit(do_something, sec) for sec in secs]

为什么?with语句在多线程中会有这样的行为,是什么原因导致了这种情况?

2个回答

6
使用with语句中的concurrent.futures.Executor,等同于在使用后调用Executor.shutdown - 导致执行器等待所有任务完成。在with块内部发生错误时,with中使用的Executor保证了并发任务的正确关闭。

Executor.shutdown(wait=True)

通知执行器应在当前挂起的未来完成执行时释放正在使用的任何资源。在关机后调用Executor.submit()Executor.map()将引发RuntimeError异常。

[...]

如果使用with语句,则可以避免显式调用此方法,它将关闭Executor(等待就像设置了waitTrue一样):


4

concurrent.futures文档不够详细。创建执行器后,必须关闭以终止其线程或进程。该代码将通过向线程推送None命令来发出退出信号,然后等待它们完成。在你的第一个案例中,如果添加了executor.shutdown(),就会看到延迟。无论如何,程序仍需要10秒才能退出。

执行器可以用作上下文管理器(具有__enter____exit__方法)。当它退出“with”块时,__exit__被调用,并为您执行shutdown调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接