hscho070 hscho070
hscho070 hscho070

Reputation: 31

Problems using asyncio in Thread

There is no problem using asyncio as follows.

import asyncio


async def main():
    await asyncio.sleep(1)
    aaa = 1
    print (aaa)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

However, I have to use asyncio within Thread as shown in the simple code below, which results in an error as follows

import asyncio
import threading

async def main():
    await asyncio.sleep(1)
    aaa = 1
    print (aaa)


def test():
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()


t=threading.Thread(target=test)
t.start()

Error Message (RuntimeError: There is no current event loop in thread 'Thread-1'.)

Exception in thread Thread-1:
Traceback (most recent call last):
  File "D:\Anaconda3\Lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "D:\Anaconda3\Lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "D:/Test/Test4/main.py", line 57, in test
    loop = asyncio.get_event_loop()
  File "D:\Anaconda3\Lib\asyncio\events.py", line 639, in get_event_loop
    raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.

How can I use asyncio in Thread?

This is very important to me. I've been struggling with this problem for two days.

I would appreciate your help.

Upvotes: 3

Views: 3870

Answers (2)

MisterMiyagi
MisterMiyagi

Reputation: 52099

Unless you need to work with a pre-existing event loop (not the case here) or support Python 3.6, use asyncio.run instead of manually handling the loop:

def test():
    asyncio.run(main())

This always ensures that there is a valid event loop, and also handles proper cleanup.

This function always creates a new event loop and closes it at the end. It should be used as a main entry point for asyncio programs, and should ideally only be called once.


Note that when combining asyncio with threads, the event loop should generally be run in the main loop (see e.g. bpo#34697). Instead of spawning a thread for asyncio, prefer to spawn one for the synchronous parts of your program.

# launch synchronous work in child threads
t=threading.Thread(target=my_sync_tasks)
t.start()

# launch asynchronous work in main thread
asyncio.run(main())
t.join()

Upvotes: 3

Guy
Guy

Reputation: 50949

When using a thread other than the main thread you need to set the event loop

def test():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(main())
    loop.close()

Upvotes: 1

Related Questions