在不阻塞的情况下使用ThreadPoolExecutor

2024-04-20 15:23:02 发布

您现在位置:Python中文网/ 问答频道 /正文

作为this question的后续内容,我有一个小脚本,它启动threadpoolexecutor来读取json文件。在这样做的时候,我希望使用for循环从1数到9。出于某些原因,即使我使用了executor.shutdown(wait=False),它仍然阻塞并等待read_employees方法执行。在

根据documentation

If wait is False then this method will return immediately and the resources associated with the executor will be freed when all pending futures are done executing

import concurrent.futures
import json
import time


def read_employees(read_file):
    with open(read_file) as f_obj:
        employees = json.load(f_obj)

    for emp in employees:
        print(emp)
        time.sleep(3)


def start_thread():
    filename = 'employee.json'
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
        executor.submit(read_employees, filename)
        executor.shutdown(wait=False)

def print_number():
    for num in range(1,10):
        time.sleep(2)
        print(num)


start_thread()
print_number()

如果我要这么做:

^{pr2}$

它先从1数到9,然后打印出员工,延迟是因为在阅读员工时睡觉。是这样的:

1
2
3
4
5
6
7
8
9
ams@yourcompanyname.com
bcs@yourcompanyname.com

如何在不阻塞的情况下使用threadpoolexecutor实现相同的输出?在


Tags: importjsonfalseforreadtimedefwith
2条回答

我建议您不要使用with语句。with语句通过调用context manager__exit__方法来关闭。上下文管理器是实现__enter____exit__方法的任何类。因此,在with语句中运行所有内容之后,它将调用传入的上下文管理器上的__exit__。在

在本例中,ThreadPoolExecutor是一个上下文管理器。ThreadPoolExecutor是{}的子类。因此,通过引用^{}'s class definition,我们看到在它的__exit__方法中,它调用了self.shutdown(wait=True)。在

self.shutdown(wait=True)的调用就是问题所在。如果遵循上下文管理器的工作方式,因为self.shutdown(wait=False)with语句中的最后一个内容,__exit__将直接在后面调用。这意味着self.shutdown(wait=True)将被调用。所以这就是阻碍你的原因。在

你有两个选择来解决这个问题。第一种方法是将ThreadPoolExecutor子类化并重写__exit__方法。在

第二种选择是这样做:

^{1}$

可能是因为这个小片段:

如果使用with语句,则可以避免显式调用此方法,该语句将关闭Executor(就像调用wait时,wait设置为True一样等待)

https://docs.python.org/3/library/concurrent.futures.html

相关问题 更多 >