[issue34476] asyncio.sleep(0) not documented

New submission from Hrvoje Nikšić <hniksic@gmail.com>: Looking at the implementation and at the old issue at https://github.com/python/asyncio/issues/284 shows that asyncio.sleep special-cases asyncio.sleep(0) to mean "yield control to the event loop" without incurring additional overhead of sleeping. However, this is not documented at https://docs.python.org/3/library/asyncio-task.html#asyncio.sleep . I propose to add to the documentation a statement along the lines of: """ A delay of 0 will relinquish control to the event loop, allowing other tasks and callbacks to run. The control will be returned to the coroutine as soon as they have run, without an explicit delay. """ ---------- assignee: docs@python components: Documentation, asyncio messages: 323949 nosy: asvetlov, docs@python, hniksic, yselivanov priority: normal severity: normal status: open title: asyncio.sleep(0) not documented versions: Python 3.7 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Hrvoje Nikšić <hniksic@gmail.com> added the comment: Also, the "Create a coroutine ..." wording in the current documentation is a bit strange - sleep() is already marked as a coroutine, and documentation of other coroutines simply state their effect in imperative. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by Karthikeyan Singaravelan <tir.karthi@gmail.com>: ---------- nosy: +xtreak _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: `asyncio.sleep()` always pauses the current task and switches execution to another one. `asyncio.sleep(0)` has no special meaning (but it has internal optimization for the case). Basically the same as `time.sleep(0)` for multithreaded program. I doubt if we need to blow the documentation with all possible related details. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Hrvoje Nikšić <hniksic@gmail.com> added the comment: The issue is because the current documentation *doesn't* say that "`asyncio.sleep()` always pauses the current task and switches execution to another one", it just says that it "blocks for _delay_ seconds". With that description a perfectly valid implementation could be further optimized with: async def sleep(delay): if delay <= 0: return ... In which case `await sleep(0)` would *not* cause a task switch. And this is not an unreasonable thing to expect because there are many other potentially-switching situations in asyncio that sometimes don't cause a switch, such as await `queue.get()` from a non-empty queue or await `await stream.readline()` from a socket stream that has a line to provide. The user who wants to implement a "yield control to event loop" has to look at the source to find out how delay==0 is handled, and then they have to wonder if it's an implementation detail. https://github.com/python/asyncio/issues/284 states that the behavior is explicit and here to stay, but that promise has never made it into the actual documentation. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: Adding "`asyncio.sleep()` always pauses the current task and switches execution to another one" sounds totally reasonable to me (without mentioning zero `delay` special case). Would you make a pull request? ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by Roundup Robot <devnull@psf.upfronthosting.co.za>: ---------- keywords: +patch pull_requests: +9035 stage: -> patch review _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Hrvoje Nikšić <hniksic@gmail.com> added the comment: Agreed about the special case. Minor change suggestion: ``sleep()` always suspends the current task, allowing other tasks to run. That is, replace "switches execution to another [task]" because there might not be other tasks or they might not be executable - the idea is to allow them to run. Also, replace "pause" with "suspend" (because when delay<=0 there is not really a discernible pause). https://github.com/python/cpython/pull/9643 If you'd still prefer the previous wording, I'll amend the PR. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: New changeset cd602b8af2d14ff686261eeb18b80f718bb16550 by Andrew Svetlov (Hrvoje Nikšić) in branch 'master': bpo-34476: Document that asyncio.sleep() always suspends. (#9643) https://github.com/python/cpython/commit/cd602b8af2d14ff686261eeb18b80f718bb... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by miss-islington <mariatta.wijaya+miss-islington@gmail.com>: ---------- pull_requests: +9045 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: New changeset 655608a1112e592cd6a9155ebe774dd285f561f3 by Andrew Svetlov (Miss Islington (bot)) in branch '3.7': bpo-34476: Document that asyncio.sleep() always suspends. (GH-9643) (#9654) https://github.com/python/cpython/commit/655608a1112e592cd6a9155ebe774dd285f... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: thanks! ---------- resolution: -> fixed stage: patch review -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by Andrew Svetlov <andrew.svetlov@gmail.com>: ---------- versions: +Python 3.8 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Hrvoje Nikšić <hniksic@gmail.com> added the comment: Also, the "Create a coroutine ..." wording in the current documentation is a bit strange - sleep() is already marked as a coroutine, and documentation of other coroutines simply state their effect in imperative. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by Karthikeyan Singaravelan <tir.karthi@gmail.com>: ---------- nosy: +xtreak _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: `asyncio.sleep()` always pauses the current task and switches execution to another one. `asyncio.sleep(0)` has no special meaning (but it has internal optimization for the case). Basically the same as `time.sleep(0)` for multithreaded program. I doubt if we need to blow the documentation with all possible related details. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Hrvoje Nikšić <hniksic@gmail.com> added the comment: The issue is because the current documentation *doesn't* say that "`asyncio.sleep()` always pauses the current task and switches execution to another one", it just says that it "blocks for _delay_ seconds". With that description a perfectly valid implementation could be further optimized with: async def sleep(delay): if delay <= 0: return ... In which case `await sleep(0)` would *not* cause a task switch. And this is not an unreasonable thing to expect because there are many other potentially-switching situations in asyncio that sometimes don't cause a switch, such as await `queue.get()` from a non-empty queue or await `await stream.readline()` from a socket stream that has a line to provide. The user who wants to implement a "yield control to event loop" has to look at the source to find out how delay==0 is handled, and then they have to wonder if it's an implementation detail. https://github.com/python/asyncio/issues/284 states that the behavior is explicit and here to stay, but that promise has never made it into the actual documentation. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: Adding "`asyncio.sleep()` always pauses the current task and switches execution to another one" sounds totally reasonable to me (without mentioning zero `delay` special case). Would you make a pull request? ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by Roundup Robot <devnull@psf.upfronthosting.co.za>: ---------- keywords: +patch pull_requests: +9035 stage: -> patch review _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Hrvoje Nikšić <hniksic@gmail.com> added the comment: Agreed about the special case. Minor change suggestion: ``sleep()` always suspends the current task, allowing other tasks to run. That is, replace "switches execution to another [task]" because there might not be other tasks or they might not be executable - the idea is to allow them to run. Also, replace "pause" with "suspend" (because when delay<=0 there is not really a discernible pause). https://github.com/python/cpython/pull/9643 If you'd still prefer the previous wording, I'll amend the PR. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: New changeset cd602b8af2d14ff686261eeb18b80f718bb16550 by Andrew Svetlov (Hrvoje Nikšić) in branch 'master': bpo-34476: Document that asyncio.sleep() always suspends. (#9643) https://github.com/python/cpython/commit/cd602b8af2d14ff686261eeb18b80f718bb... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by miss-islington <mariatta.wijaya+miss-islington@gmail.com>: ---------- pull_requests: +9045 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: New changeset 655608a1112e592cd6a9155ebe774dd285f561f3 by Andrew Svetlov (Miss Islington (bot)) in branch '3.7': bpo-34476: Document that asyncio.sleep() always suspends. (GH-9643) (#9654) https://github.com/python/cpython/commit/655608a1112e592cd6a9155ebe774dd285f... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Andrew Svetlov <andrew.svetlov@gmail.com> added the comment: thanks! ---------- resolution: -> fixed stage: patch review -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________

Change by Andrew Svetlov <andrew.svetlov@gmail.com>: ---------- versions: +Python 3.8 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue34476> _______________________________________
participants (5)
-
Andrew Svetlov
-
Hrvoje Nikšić
-
Karthikeyan Singaravelan
-
miss-islington
-
Roundup Robot