[Python-Dev] Importance of "async" keyword

Steve Dower Steve.Dower at microsoft.com
Mon Jul 6 04:03:01 CEST 2015

"A) I can call a function and might get a return value.
B) I can await an awaitable and might get a return value.
C) I cannot use them interchangeably. Why?"

Function != awaitable - the answer is right there in the terminology. Different names, different things.

Given A, B and the fact that an awaitable is just an object, here's another important point:

* I can call a function and might get an awaitable.

If the function was decorated with async, the "might" becomes "will", but it's still just a function returning a value.

Because an awaitable is indistinguishable from any other value, the compiler doesn't know whether to await or not, so it has to be specified by the developer. If the language specifies it, then it's impossible to handle awaitable objects (for example, to put them in a list and await them later).

C# is another language that implemented this exact model a few years ago and it works well.


Top-posted from my Windows Phone
From: Sven R. Kunze<mailto:srkunze at mail.de>
Sent: ‎7/‎5/‎2015 14:50
To: python-dev at python.org<mailto:python-dev at python.org>
Subject: Re: [Python-Dev] Importance of "async" keyword

Thanks, Nick, for you reasoned response.

On 03.07.2015 11:40, Nick Coghlan wrote:
> On 3 July 2015 at 06:55, Sven R. Kunze <srkunze at mail.de> wrote:
>> My understanding of coloring is "needs special treatment".
>> Being special or not (containing an 'await' or not), as long as I don't need
>> to care, I can call them either way (with 'await' or not) and each case
>> works sensibly that's fine with me.
> I'm afraid you're going to be disappointed in that regard, as wishing
> that event driven programs behaved more like synchronous programs is
> like wishing that complex numbers behaved like real numbers.
Seems like we stick to this example once again. So, let me get this

1) I can add, subtract, multiply and divide real numbers.
2) I can add, subtract, multiply and divide complex numbers.
3) I can even add, subtract, multiply and divide complex numbers AND
real numbers altogether in a single expression.
4) Granted, complex numbers can do more but that basically follows from
their definition and does not jeopardize ease of usage.

A) I can call a function and might get a return value.
B) I can await an awaitable and might get a return value.
C) I cannot use them interchangeably. Why? Because people think we
cannot have the best things of both worlds.
D) Granted, awaitables can do more but that basically follows from their
definition and does not need to jeopardize ease of usage.

> There's
> an extra level of complexity that is being deliberately introduced in
> order to improve Python's ability to express certain kinds of
> algorithms, and it isn't effective to just try to wish that complexity
> away.
> The payoff is that code that otherwise needs to be written as a long
> series of disconnected callback chains (as has long been possible with
> Twisted) can instead be written to look more like comparable
> synchronous code

That is great. So, let's do the next step.

> (and this approach should bring with it much improved
> introspection support, at least in 3.5+ now that gi_yieldfrom and
> cr_await are being exposed at the Python level).
>> Sensible would be something similar to:
>> await function: suspension point and runs the function until completion
>> call awaitable: runs the awaitable until completion
> These both fail, and deliberately so: we don't know what they're
> supposed to mean, and we refuse the temptation to guess.

Where do we guess here? It is a definition.

> They're also
> quite likely to indicate a bug (e.g. forgetting to call a native
> coroutine function to get the coroutine out of it, forgetting to wait
> for an awaitable) rather than something folks have done deliberately.
> It's possible shorthand adapters may emerge over time, like:
>      # Call awaitable from synchronous code
>      def wait_for_result(awaitable):
>          """Usage: result = asyncio.wait_for_result(awaitable)"""
>         return asyncio.get_event_loop().run_until_complete(awaitable.__await__())
>      # Call blocking operation from asynchronous code
>     def blocking_call(f, *args, **kwds):
>          """Usage: result = await asyncio.blocking_call(f, *args, **kwds))"""
>          cb = functools.partial(f, *args, **kwds)
>          return asyncio.get_event_loop().run_in_executor(cb)
> However, those can be written already as utility functions, so we can
> wait and see how strong the demand is for them as adapters. (They may
> also be potentially useful to have as recipes in the documentation)
Sure, that would be reasonable. You have the first guy asking explicitly
for these types of adapters provided by the current syntax and removal
of 'async'.

Until a solution, we return to watching and have one reason less to
switch to Python 3. :-/
Python-Dev mailing list
Python-Dev at python.org
Unsubscribe: https://mail.python.org/mailman/options/python-dev/steve.dower%40microsoft.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20150706/de6b64a6/attachment-0001.html>

More information about the Python-Dev mailing list