Future对象本身函数进行绑定,所以想要让事件循环获取Future的结果,则需要手动设置。而Task对象继承了Future对象,其实就对Future进行扩展,他可以实现在对应绑定的函数执行完成之后,自动执行set_result
,从而实现自动结束。
虽然,平时使用的是Task对象,但对于结果的处理本质是基于Future对象来实现的。
扩展:支持 await 对象
语 法的对象课成为可等待对象,所以 协程对象
、Task对象
、Future对象
都可以被成为可等待对象。
3.2.5 futures.Future对象
在Python的concurrent.futures
模块中也有一个Future对象,这个对象是基于线程池和进程池实现异步操作时使用的对象。
1
2
3
4
5
6
7
8
9
10
11
12
|
port time from concurrent.futures import Future from concurrent.futures.thread import ThreadPoolExecutor from concurrent.futures.process import ProcessPoolExecutor def func(value): time.sleep( 1 ) print (value) pool = ThreadPoolExecutor(max_workers = 5 ) # 或 pool = ProcessPoolExecutor(max_workers=5) for i in range ( 10 ): fut = pool.submit(func, i) print (fut) |
两个Future对象是不同的,他们是为不同的应用场景而设计,例如:concurrent.futures.Future
不支持await语法 等。
官方提示两对象之间不同:
-
unlike asyncio Futures,
concurrent.futures.Future
instances cannot be awaited. -
asyncio.Future.result()
andasyncio.Future.exception()
do not accept the timeout argument. -
asyncio.Future.result()
andasyncio.Future.exception()
raise anInvalidStateError
exception when the Future is not done. -
Callbacks registered with
asyncio.Future.add_done_callback()
are not called immediately. They are scheduled withloop.call_soon()
instead. -
asyncio Future is not compatible with the
concurrent.futures.wait()
andconcurrent.futures.as_completed()
functions.
在Python提供了一个将futures.Future
对象包装成asyncio.Future
对象的函数 asynic.wrap_future
。
接下里你肯定问:为什么python会提供这种功能?
其实,一般在程序开发中我们要么统一使用 asycio 的协程实现异步操作、要么都使用进程池和线程池实现异步操作。但如果 协程的异步
和 进程池/线程池的异步
混搭时,那么就会用到此功能了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import time import asyncio import concurrent.futures def func1(): # 某个耗时操作 time.sleep( 2 ) return "SB" async def main(): loop = asyncio.get_running_loop() # 1. Run in the default loop's executor ( 默认ThreadPoolExecutor ) # 第一步:内部会先调用 ThreadPoolExecutor 的 submit 方法去线程池中申请一个线程去执行func1函数,并返回一个concurrent.futures.Future对象 # 第二步:调用asyncio.wrap_future将concurrent.futures.Future对象包装为asycio.Future对象。 # 因为concurrent.futures.Future对象不支持await语法,所以需要包装为 asycio.Future对象 才能使用。 fut = loop.run_in_executor( None , func1) result = await fut print ( 'default thread pool' , result) # 2. Run in a custom thread pool: # with concurrent.futures.ThreadPoolExecutor() as pool: # result = await loop.run_in_executor( # pool, func1) # print('custom thread pool', result) # 3. Run in a custom process pool: # with concurrent.futures.ProcessPoolExecutor() as pool: # result = await loop.run_in_executor( # pool, func1) # print('custom process pool', result) asyncio.run(main()) |