← index #8340Issue #8515
Related · high · value 0.843
QUERY · ISSUE

Using asyncio in _thread

openby yjchunopened 2022-02-22updated 2022-03-29
extmod

Hello.
This might be a feature request: asyncio is missing support for threading

import uasyncio as asyncio
import _thread
import time


async def test1(arg):
    try:
        while True:
            print(arg)
            await asyncio.sleep(1)

    except Exception as e:
        print('Exception in '+arg)
        print(e)


def run(arg):
    try:
        asyncio.run(test1(arg))
    except Exception as e:
        print('Exception in asyncio.run ' + arg)
        print(e)
    print("END "+arg)


_thread.start_new_thread(run, ('core1',))
time.sleep_ms(100)
run('core0')

Tested in two ports: unix with uasyncio module included and rp2 with https://github.com/micropython/micropython/pull/8310 patch
Exception within a few seconds in both ports.
Sometimes ValueError: generator already executing
Sometimes 'NoneType' object has no attribute 'ph_child'

Also I would like to create new event loop in new thread (which is automatically done in CPython). Do you think it is possible to implement proper event loop? or would there be limitations in VM? (is generator is thread safe in VM level?)

CANDIDATE · ISSUE

uasyncio : missing RuntimeError: This event loop is already running

openby fragmuffinopened 2022-04-10updated 2026-03-23
extmodport-unix

I've just spent far too long debugging, what is essentially the following code:

#!/usr/bin/env python
try:
    import asyncio
except ImportError:
    import uasyncio as asyncio

loop = asyncio.get_event_loop()

async def foo():
    print('foo()')

async def main():
    loop.run_until_complete(foo())
    while True:
        print('app_loop()')
        await asyncio.sleep(1)

if __name__ == '__main__':
    loop.run_until_complete(main())

I know what you're thinking.... why run_until_complete inside an async function.
I completely agree, and now that I have the root cause, it's easy to fix.

However: this was nested inside a relatively large code-base, and I had no trace-back leading me to the root cause.
Finding this required a lot of cutting code until the problem went away, which wasn't helped by it being in 2 places.

Run on CPython

When run on Python 3.9.9, it raises.

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File "<stdin>", line 2, in main
  File "/usr/lib/python3.9/asyncio/base_events.py", line 623, in run_until_complete
    self._check_running()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 583, in _check_running
    raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running

Run on micropython

When the above code is executed in micropython I get the following output.

MicroPython v1.17 on 2021-09-02; PYBD-SF6W with STM32F767IIK
Type "help()" for more information.
>>> 
paste mode; Ctrl-C to cancel, Ctrl-D to finish
=== # ... above code pasted here
=== 
foo()
app_loop()
>>> 

Execution took 1 second, no exception raised.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied