Python 3 中的异步

coroutine, Future, Task

Pyhton 3 的 asyncio 模块引入了 coroutine Future Task 三个新概念,要使用 asyncio 模块进行异步程序开发,就必须要先了解这三个概念。

  • coroutine 译为协程,是 asyncio 事件循环的最小调度单位,类比于操作系统中的进程与线程,是 asyncio 事件循环中的最小调度单位。
  • Future 暂时没有明确的翻译,类比于js中的 promise ,用于等待一个未来发生的事件,常见于 io 操作,用于封装回调函数中的异步执行部分。
  • TaskFuture 的子类,用于调度 coroutine 的执行。

Future 是异步操作中的核心概念,封装了一个 coroutine 中的异步操作,常见于 io 等待。 coroutine 是一个静态概念,处在未执行状态,执行状态的 coroutine 就是 Task

在一个事件循环中同时只调度一个 Task 在执行,与操作系统中的时间片调度不同, 只有一个 Task 需要等待 Future 发生时才能调度其他的 Task 执行。

因此 coroutine 中理应至少有一个需要等待的 Future 操作,否则无法实现异步操作,也就没有了意义。不过这并非强制性的,我们完全可以定义一个与一般函数一样的 coroutine

coroutine的创建

@asyncio.coroutine 或者使用新的关键字 async def

coroutine 的执行

像调用其他函数一样调用一个 coroutine 并不会执行,只会返回一个 coroutine 对象。调度这个 coroutine 对象的方法包括:

  • 在其他协程中调用: await coroutine / yield from coroutine – await 应该优先使用。
  • 使用 ensure_future()AbstractEventLoop.create_task() 方法来调度协程执行

Future 的创建

不推荐使用 future = asyncio.Future() ,优先使用 AbstractEventLoop.create_future() ,事件循环的不同实现可能会实现不同的 Future 类。

concurrent.futures.Future

concurrent.futures.FutureExecutor.submit() 创建。

可以使用 asyncio.wrap_future(Future)concurrent.futures.Future 包装为 asyncio.future

异常捕获

应该在 coroutine 执行的地方捕获异常,在从 Future 获取结果的时候获得异常的详细信息, Future.exception() 可以获得设置给 Future 的异常。