# Async generator missing unawaited coroutine warning

**URL:** <https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563>\
**Category:** Async-SIG\
**Created:** [July 21, 2022, 5:22pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563 "2022-07-21T17:22:06Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![graingert](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/graingert/32/26847_2.png) [@graingert](https://discuss.python.org/u/graingert)\
**Post date:** [July 21, 2022, 5:22pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/1 "2022-07-21T17:22:06Z")

</div>

demo program:

```auto
def test_async_fn():
    async def async_fn():
        pass

    async_fn()

def test_async_gen_fn():
    async def agen_fn():
        yield

    agen_fn().aclose()
    agen_fn().asend(None)

test_async_fn()
test_async_gen_fn()

```

output:

```auto
/home/graingert/projects/anyio/foo.py:5: RuntimeWarning: coroutine 'test_async_fn.<locals>.async_fn' was never awaited
  async_fn()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

```

expected:

```auto
/home/graingert/projects/anyio/foo.py:5: RuntimeWarning: coroutine 'test_async_fn.<locals>.async_fn' was never awaited
  async_fn()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/home/graingert/projects/anyio/foo.py:12: RuntimeWarning: coroutine '<async_generator_athrow object at 0xffffffffffff>' was never awaited
  agen_fn().aclose()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/home/graingert/projects/anyio/foo.py:13: RuntimeWarning: coroutine '<async_generator_asend object at 0xffffffffffff>' was never awaited
  agen_fn().asend(None)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

```

---

<div class="post-metadata">

**Author:** ![graingert](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/graingert/32/26847_2.png) [@graingert](https://discuss.python.org/u/graingert)\
**Post date:** [July 21, 2022, 5:22pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/2 "2022-07-21T17:22:42Z")

</div>

Originally posted as a bug [async generator missing unawaited coroutine warning · Issue #89091 · python/cpython · GitHub](https://github.com/python/cpython/issues/89091)

---

<div class="post-metadata">

**Author:** ![graingert](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/graingert/32/26847_2.png) [@graingert](https://discuss.python.org/u/graingert)\
**Post date:** [July 21, 2022, 5:31pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/3 "2022-07-21T17:31:15Z")

</div>

interestingly cython functions do raise a runtime warning here:

```auto
Python 3.11.0b4 (main, Jul 11 2022, 23:00:23) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import helloworld
>>> helloworld.hello_agen
<cyfunction hello_agen at 0x7feef58b4860>
>>> helloworld.hello_agen().asend
<built-in method asend of async_generator object at 0x7feef58cefc0>
sys:1: RuntimeWarning: coroutine 'hello_agen' was never awaited
>>> import inspect
>>> inspect.iscoroutinefunction(helloworld.hello_agen().asend)
/usr/lib/python3.11/inspect.py:414: RuntimeWarning: coroutine 'hello_agen' was never awaited
  return _has_code_flag(obj, CO_COROUTINE)
<stdin>:1: RuntimeWarning: coroutine 'hello_agen' was never awaited
False
>>> inspect.isasyncgenfunction(helloworld.hello_agen().asend)
/usr/lib/python3.11/inspect.py:422: RuntimeWarning: coroutine 'hello_agen' was never awaited
  return _has_code_flag(obj, CO_ASYNC_GENERATOR)
False
>>> inspect.isgeneratorfunction(helloworld.hello_agen().asend)
/usr/lib/python3.11/inspect.py:407: RuntimeWarning: coroutine 'hello_agen' was never awaited
  return _has_code_flag(obj, CO_GENERATOR)
False

```

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [July 21, 2022, 7:42pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/4 "2022-07-21T19:42:23Z")

</div>

Pretty sure these are triggered by ` __del__ `, which likely means a reference is being held around in the Python implementation that Cython is releasing more eagerly. It might even be leaking? But more likely it’s getting cleaned up with the rest of the runtime, but too late to display warnings.

---

<div class="post-metadata">

**Author:** ![graingert](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/graingert/32/26847_2.png) [@graingert](https://discuss.python.org/u/graingert)\
**Post date:** [July 21, 2022, 8:40pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/5 "2022-07-21T20:40:23Z")

</div>

the same behaviour happens even if the garbage collector is disabled and using a `sys.unraisablehook` set

generator functions finalization is handled in genobject.c

> <https://github.com/python/cpython/blob/3b4ee855bd89c33176f73331002008bd35daf8cf/Objects/genobject.c#L80-L83>

and async gen functions fail the check because they set CO\_ASYNC\_GENERATOR instead of CO\_COROUTINE

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [July 21, 2022, 9:08pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/6 "2022-07-21T21:08:30Z")

</div>

Ah, well that should be an easy fix then, right?

Should the generator also set `CO_COROUTINE`? Seems like the check should just be updated to check for `CO_ASYNC_GENERATOR` as well

---

<div class="post-metadata">

**Author:** ![graingert](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/graingert/32/26847_2.png) [@graingert](https://discuss.python.org/u/graingert)\
**Post date:** [July 21, 2022, 10:02pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/7 "2022-07-21T22:02:18Z")

</div>

That’s not quite right either, because that’s when the async generator gets finalized and not when the async generator asend gets finalized, and so needs a different warning message - missing an `async with aclosing `

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [July 21, 2022, 10:26pm UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/8 "2022-07-21T22:26:07Z")

</div>

Ah I see. The automatically generated methods on the async generator don’t have the message. I bet they’re native methods and not “real” coroutines, so they likely never get registered or tracked.

I can see the value in having these warnings (and separate from the generator itself), but I have no idea the best way to implement them. Maybe additional state on the generator for each method so that the warnings can be shown when the generator is collected?

---

<div class="post-metadata">

**Author:** ![graingert](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/graingert/32/26847_2.png) [@graingert](https://discuss.python.org/u/graingert)\
**Post date:** [July 22, 2022, 12:12am UTC](https://discuss.python.org/t/async-generator-missing-unawaited-coroutine-warning/17563/9 "2022-07-22T00:12:05Z")

</div>

I think adding a finalizer to check `o->ags_state == AWAITABLE_STATE_INIT` or `o->agt_state` should do the trick?

> <https://github.com/python/cpython/blob/3b4ee855bd89c33176f73331002008bd35daf8cf/Objects/genobject.c#L1870>
