8.8. 协程

3.5 新版功能.

8.8.1. 协程函数定义

  1. async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"
  2. ["->" expression] ":" suite

Python 协程可以在多个位置上挂起和恢复执行 (参见 coroutine)。 在协程函数体内部,awaitasync 标识符已成为保留关键字;await 表达式,async for 以及 async with 只能在协程函数体中使用。

使用 async def 语法定义的函数总是为协程函数,即使它们不包含 awaitasync 关键字。

在协程函数体中使用 yield from 表达式将引发 SyntaxError

协程函数的例子:

  1. async def func(param1, param2):
  2. do_stuff()
  3. await some_coroutine()

8.8.2. async for 语句

  1. async_for_stmt ::= "async" for_stmt

asynchronous iterable 能够在其 iter 实现中调用异步代码,而 asynchronous iterator 可以在其 next 方法中调用异步代码。

async for 语句允许方便地对异步迭代器进行迭代。

以下代码:

  1. async for TARGET in ITER:
  2. BLOCK
  3. else:
  4. BLOCK2

在语义上等价于:

  1. iter = (ITER)
  2. iter = type(iter).__aiter__(iter)
  3. running = True
  4. while running:
  5. try:
  6. TARGET = await type(iter).__anext__(iter)
  7. except StopAsyncIteration:
  8. running = False
  9. else:
  10. BLOCK
  11. else:
  12. BLOCK2

另请参阅 aiter()anext() 了解详情。

在协程函数体之外使用 async for 语句将引发 SyntaxError

8.8.3. async with 语句

  1. async_with_stmt ::= "async" with_stmt

asynchronous context manager 是一种 context manager,能够在其 enterexit 方法中暂停执行。

以下代码:

  1. async with EXPR as VAR:
  2. BLOCK

在语义上等价于:

  1. mgr = (EXPR)
  2. aexit = type(mgr).__aexit__
  3. aenter = type(mgr).__aenter__(mgr)
  4.  
  5. VAR = await aenter
  6. try:
  7. BLOCK
  8. except:
  9. if not await aexit(mgr, *sys.exc_info()):
  10. raise
  11. else:
  12. await aexit(mgr, None, None, None)

另请参阅 aenter()aexit() 了解详情。

在协程函数体之外使用 async with 语句将引发 SyntaxError

参见

  • PEP 492 - 使用 async 和 await 语法实现协程
  • 将协程作为 Python 中的一个正式的单独概念,并增加相应的支持语法。

脚注

  • 1
  • 异常会被传播给发起调用栈,除非存在一个 finally 子句正好引发了另一个异常。 新引发的异常将导致旧异常的丢失。

  • 2

  • 作为函数体的第一条语句出现的字符串字面值会被转换为函数的 doc 属性,也就是该函数的 docstring

  • 3

  • 作为类体的第一条语句出现的字符串字面值会被转换为命名空间的 doc 条目,也就是该类的 docstring