-
前言
async/await是Python3.5提出的用于规范异步编程的语法糖,理解起来比较困难,前面研究了几天还是迷迷糊糊,今天在其基础上,再细读一遍。
-
发展历史
Python3.3–>yield from (关键字)
Python3.4–>asyncio (标准库)
以上两者结合,产生了Python3.5–>async/await (关键字)
so,anyone want to truly understand how
async/await
work should knowyield
andasyncio
first, and also coroutine.- about the keyword
yield
,see the artical《理解Python关键字yield与generator》 asyncio
is an event loop framework which allowed for asynchronous programing.《理解Python异步中的事件循环(asyncio管理事件循环)》coroutine
,according to Wikipedia, “Coroutines are computer program components that generalize subroutines for nonpreemptive multitasking, by allowing multiple entry points for suspending and resuming execution at certain locations”.In other words, coroutines are functions whose execution you can pause.which sounds like generators,but acctually not.
- about the keyword
-
The way it(async/await) was in Python 3.4
在asyncio之前,Python采用concurrent programming的方式来实现asynchronous programming。
import asyncio # Borrowed from http://curio.readthedocs.org/en/latest/tutorial.html. @asyncio.coroutine def countdown(number, n): while n > 0: print('T-minus', n, '({})'.format(number)) yield from asyncio.sleep(1) n -= 1 loop = asyncio.get_event_loop() tasks = [ asyncio.ensure_future(countdown("A", 2)), asyncio.ensure_future(countdown("B", 3))] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
在Python3.4用asyncio.coroutine装饰器来标识一个函数为coroutine。也就是意味着使用asyncio及其event loop。
因为generator和coroutine之间有些定义上的混淆,故此使用这个装饰器来区别coroutine。
With this concrete definition of a coroutine(Which matched an API that generators provided), you then used
yield from
on anyasyncio.Future
object to pass it down to the event loop,pausing execution of the coroutine while you waited for something to happen.Once the future object reached the event loop it was monitored there until the future object was done doing whatever it needed to do.
Once the future was done doing its thing, the event loop noticed and the coroutine that was paused waiting for the future’s result started again with its result sent back into the coroutine into the coroutine using its
send()
method.async def function(): # coroutine ... yield from asyncio.future # future
Take our example above.The event loop starts each of the
countdown()
coroutine calls, executing until it hitsyield from
and theasyncio.sleep()
function in one of them. That returns anasyncio.Future
object which gets passed down to the event loop and pauses execution of the coroutine.There the event loop watches the future object until the one second is over(as well as checking on other stuff it’s watching, like the other coroutine). Once the one second is up, the event loop takes the pausedcountdown()
coroutine that gave the event loop the future object,sends the result of the future object back into the coroutine that gave it the future object in the first place, and the coroutine starts running again. This keeps going until all of thecountdown()
coroutines are finished runing and the event loop has nothing to watch. -
Going from
yield from
to await in Python 3.5In Python 3.4, a function that was flagged as a coroutine for the purposes of asynchronous programming looked like:
@asyncio.coroutine def py34_coro(): yield from stuff()
In Python 3.5,the
types.coroutine
decorator has been added to also flag a generator as a coroutine likeasyncio.coroutine
does. You can alse useasync def
to syntactically define a function as being a coroutine, although it cannot contain any form ofyield
expression; onlyreturn
andawait
are allowed for returning a value from the coroutine:async def py35_coro(): await stuff
await
operates is only valid within anasync def
.Whileawait
operates much likeyield from
,the objects that are acceotable to an await expression are different.when you call
await
on an object, it technically needs to be an awaitable object: an object that defines an__await__()
method which returns an iterator. -
Think of async/await as an API for asynchronous programming
According talk from David Beazley,
async/await
is really an API for asynchronous programming.Which means that people shouldn’t think what async/await as synonymous with asyncio, but instead think that asyncio is a framework that can utilize the async/await API for asynchronous programming.
asyncio
uses future objects as the API for talking to its event loop whilecurio
uses tuples. -
References
- How the heck does async/await work in Python 3.5? 【here is all you should know about async/await】