首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python协程

Python协程
EN

Stack Overflow用户
提问于 2017-03-06 18:42:15
回答 1查看 796关注 0票数 5

我对Javascript中的promises有一点经验。我对Python很有经验,但对它的协程还很陌生,而且有一点我不能理解:异步是从哪里开始的?

让我们考虑下面这个最小的例子:

代码语言:javascript
复制
async def gen():
    await something
    return 42

据我所知,await something把函数的执行放在一边,让主程序运行其他部分。在某种程度上,something有了新的结果,gen很快就会有结果。

如果gensomething是协程,那么从所有互联网的智慧来看,它们都是生成器。要知道生成器何时有新的可用项afaik,唯一的方法是轮询它:x=gen(); next(x)。但这是阻塞!当x有结果时,调度器如何“知道”?答案不能是“当something有一个结果时”,因为something也必须是一个生成器(因为它是一个协程)。这个参数是递归应用的。

我不能通过这个想法,在某个时候,进程将不得不坐下来同步等待。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-06 18:58:53

这里的秘诀是asyncio module。您的something对象本身必须是一个可等待的对象,并且要么依赖于更多的可等待的对象,要么必须从Future object中让步。

例如,asyncio.sleep() coroutine会生成一个Future

代码语言:javascript
复制
@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版本的向后兼容)。

请注意,未来不使用awaityield 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()的调用协程继续,等等。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42623481

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档