Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python3 asyncio There is no current event loop in thread when spawn a new thread

I can easily reproduce this issue with this example:

from threading import Thread
import asyncio

def func():
    asyncio.get_event_loop()

Thread(target=func).start()

According to document:

If there is no current event loop set in the current OS thread, the OS thread is main, and set_event_loop() has not yet been called, asyncio will create a new event loop and set it as the current one.

like image 374
Ziqi Liu Avatar asked Feb 29 '20 02:02

Ziqi Liu


People also ask

How do I stop Asyncio event loop?

Run an asyncio Event Loop run_until_complete(<some Future object>) – this function runs a given Future object, usually a coroutine defined by the async / await pattern, until it's complete. run_forever() – this function runs the loop forever. stop() – the stop function stops a running loop.

What is Asyncio event loop?

The event loop is the core of every asyncio application. Event loops run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses. Application developers should typically use the high-level asyncio functions, such as asyncio.

Does Asyncio create threads?

When we utilize asyncio we create objects called coroutines. A coroutine can be thought of as executing a lightweight thread. Much like we can have multiple threads running at the same time, each with their own concurrent I/O operation, we can have many coroutines running alongside one another.

How many times should Asyncio run () be called?

It should be used as a main entry point for asyncio programs, and should ideally only be called once. New in version 3.7.


1 Answers

Automatic assignment of a new event loop only happens on the main thread. From the source of asyncio DefaultEventLoopPolicy in events.py

def get_event_loop(self):
    """Get the event loop for the current context.

    Returns an instance of EventLoop or raises an exception.
    """
    if (self._local._loop is None and
            not self._local._set_called and
            isinstance(threading.current_thread(), threading._MainThread)):
        self.set_event_loop(self.new_event_loop())

    if self._local._loop is None:
        raise RuntimeError('There is no current event loop in thread %r.'
                            % threading.current_thread().name)

    return self._local._loop

So for a non-main thread, you have to manually set the event loop with asyncio.set_event_loop(asyncio.new_event_loop())

like image 99
syfluqs Avatar answered Oct 02 '22 09:10

syfluqs