brython-dev / brython

Brython (Browser Python) is an implementation of Python 3 running in the browser
BSD 3-Clause "New" or "Revised" License
6.37k stars 509 forks source link

Running async function without await #2470

Closed thewh1teagle closed 2 months ago

thewh1teagle commented 3 months ago

Sometimes I forget to add await to async functions calls, but it doesn't throw errors, and I find it hard to find the cause. Can you add check for that and throw error in that case? Thanks

PierreQuentel commented 3 months ago

That would not be compliant with the Python language, where this code is valid and does not throw any error or even warning

async def f():
    pass
thewh1teagle commented 3 months ago

I meaned that I forget to add await to async functions calls.

async def get_something():
  return 'hello'

async def example():
  name = get_something() # no await here
PierreQuentel commented 3 months ago

Sorry for the misunderstanding.

In the new example, CPython doesn't raise any error or warning either.

thewh1teagle commented 3 months ago

In the new example, CPython doesn't raise any error or warning either.

In CPython it will throw warning. See the following example:

import asyncio

async def get_something():
  return 'hello'

async def example():
  name = get_something() # no await here

asyncio.run(example())
 python main.py
Python\Python39\lib\asyncio\events.py:80: RuntimeWarning: coroutine 'get_something' was never awaited
  self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
PierreQuentel commented 2 months ago

Thanks, there was something missing in Brython. The commit above raises a RuntimeWarning like in CPython.

It does so when exiting the execution frame, which leads to a minor difference with CPython. In code like

async def example():
  print('example')

example()

print('ok')

Brython shows the RuntimeWarning after printing "ok", whereas CPython shows it before. I suspect that this is caused by the garbage collector : after the line example() is executed, the coroutine object is not referenced anymore and the runtime engine can immediately detect that it has not been awaited. For Brython, garbage collection is performed by the Javascript engine and it's impossible to adapt it.

With a slightly different example, CPython and Brython both report the warning after printing "ok"

async def example():
  print('example')

c = example()

print('ok')