Python何时/将不暂停协程的执行?

时间:2019-05-19 01:16:09

标签: python python-3.x async-await python-asyncio coroutine

当我在cpython 3.6上运行它时,以下程序会一次打印hello world,然后永久旋转。

作为旁注,取消注释await asyncio.sleep(0)行会使它每秒打印hello world,这是可以理解的。

import asyncio

async def do_nothing():
    # await asyncio.sleep(0)
    pass

async def hog_the_event_loop():
    while True:
        await do_nothing()

async def timer_print():
    while True:
        print("hello world")
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
loop.create_task(timer_print())
loop.create_task(hog_the_event_loop())
loop.run_forever()

此行为(一次打印hello world)对我来说很有意义,因为hog_the_event_loop从不阻塞,因此不需要暂停执行。 我可以依靠这种行为吗?当行await do_nothing()运行时,执行而不是输入do_nothing()协程,实际上可能会暂停执行并恢复timer_print() ,导致程序第二次打印hello world

更笼统地说:python什么时候会暂停执行协程并切换到另一个协程?它可能在任何上使用await关键字吗?还是仅在导致基础select调用(例如I / O,睡眠计时器等)的情况下?

其他澄清

我知道,如果hog_the_event_loop看起来像这样,那么它肯定不会使执行程序变为另一个协程:

async def hog_the_event_loop():
    while True:
        pass

我正在尝试专门解决await do_nothing()是否与以上有所不同的问题。

2 个答案:

答案 0 :(得分:2)

  

这种行为(一次打印问候世界)对我来说很有意义,因为hog_the_event_loop从不阻塞,因此不需要暂停执行。 我可以依靠这种行为吗?

是的。该行为直接取决于该语言如何指定和实现await。对于基于async / await的asyncio and other Python库,将其更改为暂停而没有等待的对象本身暂停无疑将是一项重大更改。

  

更笼统地说:python什么时候会暂停执行协程并切换到另一个协程?可能会通过使用await关键字吗?

从调用者的角度来看,任何await都可以潜在地暂停,这取决于等待的对象(也称为awaitable)。因此,特定await是否将挂起的最终决定是在等待的对象上(如果是协程,则等待它自己等待,依此类推)。等待一个不选择暂停的等待与运行普通的Python代码相同-它不会将控制权传递给事件循环。

实际暂停的叶子等待通常与IO准备或超时事件有关,但并不总是如此。例如,如果队列为空,则等待queue的项将挂起,等待run_in_executor的项将挂起,直到在另一个线程中运行的函数完成为止。

值得一提的是,asyncio.sleepexplicitly guaranteed可以暂停执行并推迟到事件循环,即使指定的延迟为0(在这种情况下,它将在下一个事件循环通过时立即恢复) )。

答案 1 :(得分:1)

No, await do_nothing() will never suspend. await propagates suspension from an awaitable by suspending the surrounding coroutine in response. But when the awaitable is already ready, there’s nothing to wait for and execution continues from the await (with a return value, in general).

A coroutine that does nothing is always ready, just like one that sleeps is ready after the time elapses. Put differently, a coroutine that just sleeps N times suspends N times—even if N is 0.