concurrent.futures调研
参考链接:
官网:https://docs.python.org/3.7/library/concurrent.futures.html
https://learnku.com/docs/pymotw/concurrentfutures-manage-pools-of-concurrent-tasks/3424#48d590
https://www.cnblogs.com/kangoroo/p/7628092.html
英文:https://pythonhosted.org/futures/
一、执行器
导入: from concurrent.futures import ThreadPoolExecutor, wait, ProcessPoolExecutor
任务Executor是一个抽象类,由ThreadPoolExecutor和ProcessPoolExecutor返回,表示线程池和进程池。 两者的 API t 相同,所以我们只需要进行少量修改即可在线程与进程间切换。提供了如下方法submit,map,shutdown。值得一提的是Executor实现了__enter__和__exit__使得其对象可以使用with操作符。
先定义两个任务函数:
def task(arg):
time.sleep(arg)
print(f'收到了{arg}')
return arg
def task1(arg):
_ = [i for i in range(10 ** 7)]
return arg
使用过程:
map()
exe = ThreadPoolExecutor(max_workers=2)
# 或者
exe = ProcessPoolExecutor(max_workers=2)
result_l = exe.map(task1, [2, 1, 3])
# print(result_l)
# <generator object Executor.map.<locals>.result_iterator at 0x7f50f1ae9258>print(list(result_l))
print(list(result_l))
# [2, 1, 3]
map()
所返回的值实际上是一个特殊的迭代器,它被主程序迭代时会等待其中的并发任务返回,没返回就一直等待map()
返回的结果却总以执行顺序有关,使用 map()
可以以原本的顺序访问多个任务的返回值。
除了使用 map()
,我们还可以用 submit()
来执行单个任务 ,也是使用的 Future
实例等待任务结果的返回。
submit()
def main2():
exe = ThreadPoolExecutor(max_workers=2)
r1 = exe.submit(task, 2)
r2 = exe.submit(task, 1)
r3 = exe.submit(task, 3)
print(r1.result(), r2.result(), r3.result())
# 运行结果
'''
收到了1
收到了2
收到了3
2 1 3'''
shutdown(self, wait=True)
释放资源,关闭执行器,关闭之后不能在添加任务。
二、模块函数: as_completed 和 wait
as_completed(fs, timeout=None)
参数:
fs 是包含future对象的序列
timeout 是最大等待时间, 单位秒,默认死等
返回:
包含future结果的迭代器, 如果future重复, 返回一次
as_completed() 返回结果与顺序无关,在某任务执行完成后立即进行处理
使用:
def main3():
exe = ThreadPoolExecutor(max_workers=2)
l = [exe.submit(task, i) for i in [2, 1, 3]]
print([f.result() for f in as_completed(l)])
'''
收到了1
收到了2
收到了3
[1, 2, 3]
不是map()按顺序执行的的[2, 1, 3]
'''
wait(fs, timeout=None, return_when=ALL_COMPLETED)
参数:
前两个参数和as_completed一样,
fs 是包含future对象的序列
timeout 是最大等待时间,单位秒,默认死等
FIRST_COMPLETED - 当任何一个future结束或取消
FIRST_EXCEPTION - 当任何一个future抛出异常时返回.如果没有抛出异常,效果和ALL_COMPLETED一样.
ALL_COMPLETED - 所有任务结束或取消时返回。
返回:
wait方法接会返回一个tuple(元组),tuple中包含两个set(集合),第一个是wait等待时间之前已完成的的future的集合(包含结束或取消),另外一个是未完成的的future的集合。
使用wait方法的一个优势就是获得更大的自由度,它接收三个参数FIRST_COMPLETED, FIRST_EXCEPTION和ALL_COMPLETE,默认设置为ALL_COMPLETED。
def main4():
exe = ThreadPoolExecutor(max_workers=2)
l = [exe.submit(task, i) for i in [2, 1, 3]]
s1, s2 = wait(l, return_when='FIRST_COMPLETED')
print([f.result() for f in s1])
print([f.result() for f in s2])
'''
return_when 默认时
收到了1
收到了2
收到了3
[1, 2, 3]
[]
return_when='FIRST_COMPLETED'
收到了1
[1]
收到了2
收到了3
[3, 2]
'''
三、future对象
submit函数返回future对象,map函数返回future对象对象的列表。
future.cancel
() 取消任务
future.cancelled
() 排断任务是否取消
future.running() 是否运行
future.done
() 是否结束add_done_callback
(fn) 添加结束或取消时的回调函数
四、异常
concurrent.futures.CancelledError
当future对象取消
concurrent.futures.TimeoutError
当future对象运行到给定时间
concurrent.futures.BrokenExecutor
执行器异常,不能调用submit,不能执行新的任务
concurrent.futures.thread.BrokenThreadPool
当线程池中的worker不能初始化
concurrent.futures.process.BrokenProcessPool
当进程被终止,比如从外部kill