Search code examples
pythonpython-3.xruntime-errorpython-asyncio

Combining loop.run_until_complete and asnycio.gather results in RuntimeError: This event loop is already running


I want to run two async functions in parallel.

This is my code:

import asyncio

async def count(label, number):
    for i in range(number):
        print(label, i)
        await asyncio.sleep(1)

async def main():
    asyncio.get_event_loop().run_until_complete(
        asyncio.gather(count("a", 3), count("b", 5))
    )

asyncio.run(main())

And this is the error I'm seeing:

$ python3 test.py 
a 0
b 0
Traceback (most recent call last):
  File "test.py", line 188, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "test.py", line 167, in main
    asyncio.get_event_loop().run_until_complete(
  File "/usr/lib/python3.9/asyncio/base_events.py", line 618, in run_until_complete
    self._check_running()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 578, in _check_running
    raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
_GatheringFuture exception was never retrieved
future: <_GatheringFuture finished exception=CancelledError()>
Traceback (most recent call last):
  File "test.py", line 188, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "test.py", line 167, in main
    asyncio.get_event_loop().run_until_complete(
  File "/usr/lib/python3.9/asyncio/base_events.py", line 618, in run_until_complete
    self._check_running()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 578, in _check_running
    raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/tasks.py", line 654, in sleep
    return await future
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

asyncio.exceptions.CancelledError

I don't understand what's going wrong. And the weirdest part is, that I think this code was working before? What's up with that? I'm currently using Python 3.9 on Debian 11. Maybe I need to try an older version to see if there is actually a difference.


Solution

  • 🤦 I found my mistake. Combining loop.run_until_complete with asnycio.gather was not the problem. I mistakenly put the asyncio.get_event_loop().run_until_complete inside an async function, too. That's also why it said that the "event loop is already running".

    This works:

    import asyncio
    
    async def count(label, number):
        for i in range(number):
            print(label, i)
            await asyncio.sleep(1)
    
    def main():
        asyncio.get_event_loop().run_until_complete(
            asyncio.gather(count("a", 3), count("b", 5))
        )
    
    main()