Python异步编程asyncio(四):Future

1 引言

在之前的文章中,我们探讨了 Coroutine (协程)——一种异步执行单元,Task (任务)——协程的调度封装。在实际的异步系统中,“产生结果的时刻”“消费结果的时刻” 往往是解耦的。当一个异步操作正在后台运行,而我们需要一个“凭证”来代表那个尚未抵达的结果时,该由谁来充当这个角色?
答案就是 Future

2 什么是Future?

Future 是一个Awaitable对象,作为我们尚未拥有但希望将来会有的结果的容器

3 Future的行为模式

3.1 状态

它是生产者设置返回值结果的标准化方式。

import asyncio

# 创建一个 Future 对象
f = asyncio.Future()

print(f"Is done? {f.done()}")       # False
print(f"Is cancelled? {f.cancelled()}") # False

# 尝试在没有结果时获取结果会抛出 InvalidStateError
try:
    f.result()
except asyncio.InvalidStateError:
    print("Result is not set yet!")

# 设置结果
f.set_result("Success!")

print(f"Is done now? {f.done()}")    # True
print(f"Result: {f.result()}")       # Success!

3.2 填充结果

通过 loop.call_later 模拟一个延迟任务,在 3 秒后填充 Future 的值。

import asyncio
import typing

async def consumer(awaitable: typing.Awaitable) -> str:
    print("Consumer: Waiting for the result...")
    # 暂停在这里,直到 awaitable (Future) 被填充
    result = await awaitable
    return f"Consumer received: {result}"

async def main():
    loop = asyncio.get_running_loop()
    f = loop.create_future()

    # 模拟 3 秒后由生产者设置结果
    loop.call_later(3, f.set_result, 'Hello Future!')

    res = await consumer(f)
    print(res)

asyncio.run(main())

3.3 填充异常

import asyncio
import typing
async def func(awaitable: typing.Awaitable)-> str:
    try:
        result = await awaitable
    except Exception as e:
        print("oops!")
        return f"Error: {e}"
    else:
        return result

f = asyncio.Future()
loop = asyncio.get_event_loop()
loop.call_later(1, f.set_exception, ValueError("test error"))

res = loop.run_until_complete(func(f))
print(res)

由于我们将 set_result 改为 set_exception,输出将是:

oops!
Error: test error

嵌套的 Awaitable 也可以工作:

res = loop.run_until_complete(func(func(f)))

输出将是:

oops!
oops!
Error: test error

它也可以与 asyncio.gather 一起工作:

res = loop.run_until_complete(asyncio.gather(func(f), func(func(f))))

输出将是:

oops!
oops!
oops!
['Error: test error', 'Error: test error']

3.4 回调机制

为 Future 添加完成 Callback:

import asyncio

def callback(fut: asyncio.Future) -> None:
    print("Future done with result:", fut.result())

loop = asyncio.new_event_loop()
f = loop.create_future()
f.add_done_callback(callback)
f.add_done_callback(lambda f: loop.stop())
f.set_result("Hello, Future!")
loop.run_forever()

输出:

Future done with result: Hello, Future!
posted @ 2026-02-05 17:58  ixbwer  阅读(3)  评论(0)    收藏  举报