Python什么时候/不会暂停协程的执行? [英] When will/won't Python suspend execution of a coroutine?

查看:64
本文介绍了Python什么时候/不会暂停协程的执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When I run it on cpython 3.6, the following program prints hello world a single time and then spins forever.

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

As a side note, uncommenting the await asyncio.sleep(0) line causes it to print hello world every second, which is understandable.

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 ?

This behavior (printing hello world a single time) makes sense to me, because hog_the_event_loop never blocks and therefore has no need to suspend execution. Can I rely on this behavior? When the line await do_nothing() runs, is it possible that rather than entering the do_nothing() coroutine, execution will actually suspend and resume timer_print(), causing the program to print hello world a second time?

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

Put more generally: When will python suspend execution of a coroutine and switch to another one? Is it potentially on any use of the await keyword? or is it only in cases where this results in an underlying select call (such as I/O, sleep timers, etc)?

我了解,如果 hog_the_event_loop 看起来像这样,那么它肯定不会执行到另一个协程:

I understand that if hog_the_event_loop looked like this, it would certainly never yield execution to another coroutine:

async def hog_the_event_loop():
    while True:
        pass

我正试图具体解决 await do_nothing()是否与上面有所不同的问题.

I'm trying to specifically get at the question of whether await do_nothing() is any different than the above.

推荐答案

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

This behavior (printing hello world a single time) makes sense to me, because hog_the_event_loop never blocks and therefore has no need to suspend execution. Can I rely on this behavior?

是的.这种行为直接取决于该语言如何指定和实现 await .对于asyncio ,将其更改为挂起而没有等待的对象本身挂起无疑将是一个重大更改.其他基于async/await的Python库.

Yes. This behavior directly follows from how await is both specified and implemented by the language. Changing it to suspend without the awaitable object having itself suspended would certainly be a breaking change, both for asyncio and other Python libraries based in async/await.

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

从调用者的角度看,任何 await 都可以潜在地挂起,具体取决于等待对象,也称为

From the caller's perspective, any await can potentially suspend, at the discretion of the awaited object, also known as an awaitable. So the final decision of whether a particular await will suspend is on the awaitable (or on awaitables it awaits itself if it's a coroutine, and so on). Awaiting an awaitable that doesn't choose to suspend is the same as running ordinary Python code - it won't pass control to the event loop.

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

The leaf awaitables that actually suspend are typically related to IO readiness or timeout events, but not always. For example, awaiting a queue item will suspend if the queue is empty, and awaiting run_in_executor will suspend until the function running in the other thread completes.

值得一提的是, asyncio.sleep 明确保证即使指定的延迟为0,也会暂停执行并推迟到事件循环(在这种情况下,它将在下一次事件循环通过时立即恢复).

It is worth mentioning that asyncio.sleep is explicitly guaranteed to suspend execution and defer to the event loop, even when the specified delay is 0 (in which case it will immediately resume on the next event loop pass).

这篇关于Python什么时候/不会暂停协程的执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆