On 2020-06-12 5:47 p.m., J. Pic wrote:
Hi all,

Currently, you can not use await outside an async function, the following code:

  async def lol():
    return 'bar'

  def test():
    return await lol()


Will fail with: SyntaxError: 'await' outside async function

Of course, you can use asyncio.run and then it works fine:

  import asyncio

  async def lol():
    return 'bar'

  def test():
    return asyncio.run(lol())


Why not make using await do asyncio.run "behind the scenes" when called outside async function ?

Thank you in advance for your replies

What if we extend awaitables to be optionally "runnable"?

An await outside async def, would map to awaitable.run(). In the specific case of coroutines, this would also automatically propagate down. E.g.

async def foo():
  await bar()

def baz()
  await foo()

A call to baz() would thus create a coroutine foo(), and then run() it. By my proposed semantics, the await bar() would also call run() on the result of bar()!

In particular, this could allow one to turn any arbitrary async coroutine into a blocking subroutine, as long as it supports this run() protocol. This would be great for refactoring existing blocking code into async - just use stuff as if it's sync, then when you're done, switch up your function with async def, and change relevant calls into it into "await" calls. Rinse and repeat until you're ready to add a top-level event loop.

Optionally, this would also allow us to deprecate blocking APIs (like open(), etc) and asyncio, and merge them into one TBD API. Perhaps as part of Python 4. (e.g. turn existing open() into await open(), particularly in non-async-def. I *think* this could be done automatically as part of some sort of "3to4", even.)


Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/LOCYSYVRKXI45QQJOLYGZV6H2CBYTB7F/
Code of Conduct: http://python.org/psf/codeofconduct/