PEP 0492 - Python 3.5异步关键字

Pau*_*son 34 python asynchronous coroutine python-3.x async-await

PEP 0492async关键字添加到Python 3.5.

Python如何从使用此运算符中受益?协程的例子是

async def read_data(db):
    data = await db.fetch('SELECT ...')
Run Code Online (Sandbox Code Playgroud)

根据这个文件实现

暂停执行read_data协同程序,直到db.fetch等待完成并返回结果数据.

async关键字是否实际涉及新线程的创建或可能使用现有的保留异步线程?

async确实使用保留线程的情况下,它们各自是一个共享线程吗?

Mar*_*ers 44

不,协同例程不涉及任何类型的线程.协同例程允许协作多任务,因为每个协同例程都自愿地产生控制.另一方面,线程在任意点的单元之间切换.

直到Python 3.4,才有可能使用生成器编写协同例程; 通过在函数体中使用yieldyield from表达式来创建生成器对象,其中代码仅在迭代生成器时执行.与其他事件循环库(例如asyncio)一起,您可以编写协同例程,这些协同例程将向一个事件循环发出信号,告知它们将要忙(等待I/O),并且可以同时运行另一个协同例程:

import asyncio
import datetime

@asyncio.coroutine
def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        yield from asyncio.sleep(1)
Run Code Online (Sandbox Code Playgroud)

每次上面的代码前进到该yield from asyncio.sleep(1)行时,事件循环可以自由运行不同的协同例程,因为这个例程无论如何都不会为下一秒做任何事情.

因为生成器可以用于各种任务,而不仅仅是协同例程,并且因为使用生成器语法编写协同例程可能会让新人感到困惑,所以PEP引入了新的语法,使您更清楚地知道您正在编写co -常规.

实施PEP后,上述样本可以改为:

async def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)
Run Code Online (Sandbox Code Playgroud)

生成的coroutine对象仍然需要一个事件循环来驱动协同例程; await依次对每个协同例程进行事件循环,这将执行那些当前没有await完成某些事情的协同例程.

优点是,通过本机支持,您还可以引入其他语法来支持异步上下文管理器和迭代器.进入和退出上下文管理器,或循环遍历迭代器,然后可以在您的协同例程中成为更多的点,表明其他代码可以运行,因为有些东西在等待.

  • @orokusaki:每次你尝试推进这个协同例程时,“await asyncio.sleep(1)”行**立即**产生*我很忙,其他人做某事*,直到一整秒过去。它永远不会“阻塞”,它只是立即产生一条特殊的“等待”消息。因为它不会阻塞,所以协同例程事件循环(轮询所有协同例程以找到“不”忙于等待的协同例程)可以运行不同的协同例程。它可以随意“轮询”这个协同例程,但是“await”行在 1 秒时间过去之前不会继续代码的其余部分。 (2认同)