作为对this question的跟进,我有一个简单的脚本,它会启动threadpoolexecutor
来读取json
文件。在这样做时,我想使用for
循环从1到9计数。出于某种原因,即使我使用executor.shutdown(wait=False)
,它仍会阻塞并等待read_employees
方法执行。
如果wait为False,则此方法将立即返回,并且当所有待处理的期货完成执行时,将释放与执行程序关联的资源
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()
如果我这样做:
def read_employees(read_file):
with open(read_file) as f_obj:
employees = json.load(f_obj)
for emp in employees:
time.sleep(5)
print(emp)
def print_number():
for num in range(1,10):
print(num)
filename = 'employee.json'
empThread = threading.Thread(target=read_employees, args=(filename,))
empThread.start()
print_number()
首先计算从1到9,然后打印出员工,延迟是因为在阅读员工时睡觉。像这样:
1
2
3
4
5
6
7
8
9
ams@yourcompanyname.com
bcs@yourcompanyname.com
如何使用threadpoolexecutor
无阻塞地实现相同的输出?
答案 0 :(得分:3)
我建议您不要使用with
声明。通过调用context manager的with
方法关闭__exit__
语句。上下文管理器是实现__enter__
和__exit__
方法的任何类。因此,在所有内容都在with
语句中运行后,它会在传入的上下文管理器上调用__exit__
。
在这种情况下,ThreadPoolExecutor
是一个上下文管理器。 ThreadPoolExecutor
是Executor
的子类。因此,通过引用Executor
's class definition,我们会在其__exit__
方法中看到它调用self.shutdown(wait=True)
。
调用self.shutdown(wait=True)
是问题所在。如果您遵循上下文管理器的工作方式,由于self.shutdown(wait=False)
是with
语句中的最后一项,__exit__
将在之后直接调用。这意味着将调用self.shutdown(wait=True)
。这就是什么阻碍了你。
您有两种方法可以解决此问题。第一个是子类ThreadPoolExecutor
并重写__exit__
方法。
第二种选择是做这样的事情:
def start_thread():
filename = 'employee.json'
executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
executor.submit(read_employees, filename)
executor.shutdown(wait=False)
答案 1 :(得分:0)
可能是由于这个小片段:
"如果使用with
语句,则可以避免必须显式调用此方法,这将关闭Executor
(等待Executor.shutdown()
被wait
调用True
1}}设置为{{1}})"