This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: asyncio.sleep(0) not documented
Type: Stage: resolved
Components: asyncio, Documentation Versions: Python 3.8, Python 3.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: docs@python Nosy List: asvetlov, docs@python, hniksic, xtreak, yselivanov
Priority: normal Keywords: patch

Created on 2018-08-23 14:41 by hniksic, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 9643 merged python-dev, 2018-09-30 08:45
PR 9654 merged miss-islington, 2018-10-01 10:09
Messages (9)
msg323949 - (view) Author: Hrvoje Nikšić (hniksic) * Date: 2018-08-23 14:41
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.
"""
msg323950 - (view) Author: Hrvoje Nikšić (hniksic) * Date: 2018-08-23 14:42
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.
msg326706 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2018-09-30 06:26
`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.
msg326709 - (view) Author: Hrvoje Nikšić (hniksic) * Date: 2018-09-30 06:58
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.
msg326713 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2018-09-30 07:46
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?
msg326717 - (view) Author: Hrvoje Nikšić (hniksic) * Date: 2018-09-30 08:49
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.
msg326781 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2018-10-01 10:09
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/cd602b8af2d14ff686261eeb18b80f718bb16550
msg326785 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2018-10-01 10:19
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/655608a1112e592cd6a9155ebe774dd285f561f3
msg326786 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2018-10-01 10:20
thanks!
History
Date User Action Args
2022-04-11 14:59:05adminsetgithub: 78657
2018-10-01 10:20:13asvetlovsetversions: + Python 3.8
2018-10-01 10:20:04asvetlovsetstatus: open -> closed
resolution: fixed
messages: + msg326786

stage: patch review -> resolved
2018-10-01 10:19:37asvetlovsetmessages: + msg326785
2018-10-01 10:09:57miss-islingtonsetpull_requests: + pull_request9045
2018-10-01 10:09:42asvetlovsetmessages: + msg326781
2018-09-30 08:49:31hniksicsetmessages: + msg326717
2018-09-30 08:45:54python-devsetkeywords: + patch
stage: patch review
pull_requests: + pull_request9035
2018-09-30 07:46:33asvetlovsetmessages: + msg326713
2018-09-30 06:58:10hniksicsetmessages: + msg326709
2018-09-30 06:26:47asvetlovsetmessages: + msg326706
2018-09-22 16:35:12xtreaksetnosy: + xtreak
2018-08-23 14:42:20hniksicsetmessages: + msg323950
2018-08-23 14:41:27hniksiccreate