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 timefrom concurrent.futures import Futurefrom concurrent.futures.thread import ThreadPoolExecutorfrom concurrent.futures.process import ProcessPoolExecutordef 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.Futureinstances cannot be awaited. -
asyncio.Future.result()andasyncio.Future.exception()do not accept the timeout argument. -
asyncio.Future.result()andasyncio.Future.exception()raise anInvalidStateErrorexception 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 timeimport asyncioimport concurrent.futuresdef 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()) |













