PEP 0492将async
关键字添加到Python 3.5。
Python如何从使用此运算符中受益?为协程提供的示例是
async def read_data(db):
data = await db.fetch('SELECT ...')
根据文件实现
暂停执行read_data协同程序,直到db.fetch等待完成并返回结果数据。
这个async
关键字实际上是否涉及创建新线程或者是否使用现有的保留异步线程?
如果async
确实使用了保留线程,那么它们是一个共享线程吗?
答案 0 :(得分:43)
不,协同例程不涉及任何类型的线程。协同例程允许协作多任务,因为每个协同例程都自愿地产生控制。另一方面,线程在任意点的单元之间切换。
在Python 3.4之前,可以使用生成器编写协同例程;通过在函数体中使用yield
或yield 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)
每次上面的代码进入yield from asyncio.sleep(1)
行时,事件循环可以自由运行不同的协同例程,因为这个例程不会为下一秒做任何事情
因为生成器可以用于各种任务,而不仅仅是协同例程,并且因为使用生成器语法编写协同例程可能会让新人感到困惑,所以PEP引入了新的语法,使其更清晰你正在写一个合作例程。
实施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)
生成的 coroutine
对象仍然需要一个事件循环来驱动协同例程;依次为每个协同例程提供一个事件循环await
,这将执行那些当前不await
完成某些事情的协同例程。
优点是,通过本机支持,您还可以引入其他语法来支持异步上下文管理器和迭代器。进入和退出上下文管理器,或循环遍历迭代器,然后可以在您的协同例程中成为更多的点,表明其他代码可以运行而不是因为某些东西再次等待。