[New-bugs-announce] [issue39085] Improve docs for await expression

Kyle Stanley report at bugs.python.org
Tue Dec 17 22:47:41 EST 2019

New submission from Kyle Stanley <aeros167 at gmail.com>:

For context, I decided to open this issue after receiving a substantial volume of very similar questions and misconceptions from users of asyncio and trio about what `await` does, mostly within a dedicated "async" topical help chat (in the "Python Discord" community). For the most part, the brief explanation provided in the language reference docs (https://docs.python.org/3/reference/expressions.html#await-expression) did not help to clear up their understanding.

Also, speaking from personal experience, I did not have a clear understanding of what `await` actually did until I gained some experience working with asyncio. When I read the language reference definition for the await expression for the first time, it did not make much sense to me either.

As a result, I think the documentation for the `await` expression could be made significantly more clear. To users that are already familiar with asynchronous programming it likely makes more sense, but I don't think it's as helpful as it could be for those who are trying to fundamentally understand how `await` works (without having prior experience):

"Suspend the execution of coroutine on an awaitable object. Can only be used inside a coroutine function."


(Also, note that there's a typo in the current version, "of coroutine" should probably be "of a coroutine")

While this explanation is technically accurate, it also looks to be the _shortest_ one out of all of the defined expressions on the page. To me, this doesn't seem right considering that the await expression is not the easiest one to learn or understand.

The vast majority of the questions and misunderstandings on `await` that I've seen typically fall under some variation of one of the following:

1) What exactly is being suspended?
2) When is it resumed/unsuspended?
3) How is it useful?

>From what I can tell, (1) is unclear to them is partly because the awaitable object that is after the `await` can be a coroutine object. It's not at all uncommon to see "await some_coro()".

I think this would be much more clear if it were to instead be something along the lines of one the following (changes indicated with *):

1) "Suspend the execution of *the current coroutine function* on an awaitable object. Can only be used inside a coroutine function."

Where "the current coroutine function" is the coroutine function that contains the await expression. I think this would help to clear up the first question, "What exactly is being suspended?".

2) "Suspend the execution of *the current coroutine function* on an awaitable object. *The coroutine function is resumed when the awaitable object is completed and returns its result*. Can only be used inside a coroutine function."

This would likely help to clear up "When is it resumed/unsuspended?".

Optimally, this definition could also include some form of example code like several of the other expressions have. It's not particularly easy to use a demonstrable example without using an async library (such as asyncio), but using a specific async library would not make sense to have in this location of the docs because the language reference is supposed to be as implementation agnostic as possible.

However, I think a very brief visual example with some explanation could still be useful for explaining the basics of how await works:

3) ```
async def coro():
    # before await
    await some_awaitable
    # after await

When the coroutine function `coro()` is executed, it will behave roughly the same as any subroutine function in the "before await" section. However, upon reaching `await some_awaitable`, the execution of `coro()` will be suspended on `some_awaitable`, preventing the execution of anything in the "after await" section until `some_awaitable` is completed. This process is repeated with successive await expressions. Also, multiple coroutines can be suspended at the same time.

Suspension can be used to indicate that other coroutines can be executed in the meantime. This can be used to write asynchronous and concurrent programs without the usage of callbacks.

Including the brief example and explanation would likely help to further clear up all three of the questions.

The present version has a high degree of technical accuracy, but I don't think its as helpful as it could be for furthering the understanding of users or providing an introduction to the await expression. I'm sure that there will still be some questions regarding `await` even if any of these changes are made, but it would at least provide a good place to link to for an informative explanation of `await` that's entirely agnostic from any specific implementation.

I'm entirely open to any alternative suggestions, or making a change that's some combination or variation of the above three ideas. Alternatively, if there are determined to be no suitable changes that would be both technically accurate and more helpful to users, I could just apply a fix to the typo.

If any of these ideas are approved, I'll likely open a PR.

assignee: aeros
components: Documentation, asyncio
messages: 358610
nosy: aeros, asvetlov, njs, yselivanov
priority: normal
severity: normal
status: open
title: Improve docs for await expression
type: enhancement
versions: Python 3.8, Python 3.9

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list