我对Javascript中的promises有一点经验。我对Python很有经验,但对它的协程还很陌生,而且有一点我不能理解:异步是从哪里开始的?
让我们考虑下面这个最小的例子:
async def gen():
await something
return 42据我所知,await something把函数的执行放在一边,让主程序运行其他部分。在某种程度上,something有了新的结果,gen很快就会有结果。
如果gen和something是协程,那么从所有互联网的智慧来看,它们都是生成器。要知道生成器何时有新的可用项afaik,唯一的方法是轮询它:x=gen(); next(x)。但这是阻塞!当x有结果时,调度器如何“知道”?答案不能是“当something有一个结果时”,因为something也必须是一个生成器(因为它是一个协程)。这个参数是递归应用的。
我不能通过这个想法,在某个时候,进程将不得不坐下来同步等待。
发布于 2017-03-06 18:58:53
这里的秘诀是asyncio module。您的something对象本身必须是一个可等待的对象,并且要么依赖于更多的可等待的对象,要么必须从Future object中让步。
例如,asyncio.sleep() coroutine会生成一个Future
@coroutine
def sleep(delay, result=None, *, loop=None):
"""Coroutine that completes after a given time (in seconds)."""
if delay == 0:
yield
return result
if loop is None:
loop = events.get_event_loop()
future = loop.create_future()
h = future._loop.call_later(delay,
futures._set_result_unless_cancelled,
future, result)
try:
return (yield from future)
finally:
h.cancel()(这里的语法使用旧的生成器语法,以保持与旧的Python 3版本的向后兼容)。
请注意,未来不使用await或yield from;他们只使用yield self until some condition is met。在上面的async.sleep()协程中,当产生一个结果时(在上面的async.sleep()代码中,通过在延迟之后调用的futures._set_result_unless_cancelled()函数)就满足了这个条件。
然后,事件循环不断地从它管理的每个挂起的未来中拉入下一个“结果”(有效地轮询它们),直到将来发出完成的信号(通过引发保存结果的StopIteration异常;例如,来自协同例程的return可以做到这一点)。在这一点上,产生未来的协程可以被发出继续的信号(通过发送未来的结果,或者如果未来引发StopIteration以外的任何异常,则抛出异常)。
因此,对于您的示例,循环将启动您的gen()协程,然后await something (直接或间接)生成一个未来。该未来会被轮询,直到它引发StopIteration (表示它已经完成)或引发其他一些异常。如果将来完成,则执行coroutine.send(result),然后允许它前进到return 42行,使用该值触发新的StopIteration异常,允许等待gen()的调用协程继续,等等。
https://stackoverflow.com/questions/42623481
复制相似问题