Python Forum

Full Version: Error: There is no current event loop in thread 'MainThread'
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Python 3.7.2

In my processing, the main function is wrapped by error interceptors and the interception is performed correctly:
try:
    downloader = Downloader.Downloader()
    downloader.download()
except Exception as err:
    General.exist_error = True
    Events.Sender.send_error(err)
But if an error occurred (and was correctly intercepted!), then the following start of processing fall down on the line:
self.event_exist_data = Event()
with error:
Error:
There is no current event loop in thread 'MainThread'
I found the place of the code in which the error occurs (module events):
class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy):
...
    def get_event_loop(self):
        """Get the event loop.

        This may be None or an instance of EventLoop.
        """
        if (self._local._loop is None and #TRUE
                not self._local._set_called and #FALSE BECAUSE self._local._set_called IS TRUE !!!
                isinstance(threading.current_thread(), threading._MainThread)): #TRUE
            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.' #On the second, third ... iteration I get here!!!
                               % threading.current_thread().name)

        return self._local._loop
I think you'll need to show more code. Especially where/how you're using event loops. Without seeing that, we can't really guess why there's a problem with the event loop.
Thank you for your interest!
There is no low-level work with the event loop anywhere, just the use of the run() method in a single place (presented below). In my code specific classes are wrapped by decorators who register them for execution in the REGISTRY list (it is currently only 1 class):
class AbstaractUnit:
    def __init__(self):
        self.fill_coroutines()
        
    @abstractmethod    
    def fill_coroutines(self): pass
    
    async def _create_workers(self) -> None:
        await asyncio.gather(*self.coroutines)
        
    def __call__(self) -> None:
        asyncio.run(self._create_workers())

class Downloader(_Unit.AbstaractUnit):
    REGISTRY = []
    
    @classmethod
    def register(cls):
        def decorator(child_class):
            cls.REGISTRY.append(child_class)
            return child_class
        
        return decorator
    
    def __init__(self):
        _Unit.AbstaractUnit.__init__(self)
        
    def fill_coroutines(self):
        self.coroutines = []
        for Method in self.REGISTRY:
            coroutine = Method()()
            self.coroutines.append(coroutine)
            
    def download(self):
        self.__call__()
In this way, I run the code for execution and intercept errors:
try:
            downloader = Downloader.Downloader()                
            downloader.download()
        except Exception as err:
            General.exist_error = True
            Events.Sender.send_error(err)
Is there any way you can put together a complete example I can run, that demonstrates the issue?
The only thing I can see, is that the manager/AbstractUnit is calling asyncio.run(), which might not be safe to call more than once.

I get that from the docs: https://docs.python.org/3/library/asynci...syncio.run
Quote:This function cannot be called when another asyncio event loop is running in the same thread.
...
Quote: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.
(Feb-20-2019, 08:21 PM)nilamo Wrote: [ -> ]I get that from the docs: https://docs.python.org/3/library/asynci...syncio.run
Quote:This function cannot be called when another asyncio event loop is running in the same thread.

Thank you!
I replaced:
asyncio.run(self._create_workers())
on this lines:
ioloop = asyncio.get_event_loop()
ioloop.run_until_complete(self._create_workers())
and the error, that occurred when the processing was restarted, disappeared.