There are so many solutions to this Runtime error on Stack Overflow that don’t work. If you write Python code using asyncio, you either have or most likely will run into this runtime error at some point. I personally came across this error while running asynchronous API requests. When you’re running an
await function using the
asyncio library, you may get a
RuntimeError: Event Loop is closed error even after your loop is already done running. This problem may not always affect the functionality of a single script but will affect the functionality of multiple scripts.
In this post we’ll go over:
- The asyncio
- The Runtime Error: Event loop is closed Problem
- Error logs from the
- Error logs from the
- The Runtime Error: Event loop is closed Solution
- Editing the Source Code of the
- Editing the Source Code of the
Click here for the source code you can copy and paste directly into your program → asyncio Runtime Error: Event Loop is closed Solution
The asyncio Library and run vs loop.run_until_complete
The aforementioned issue can come up when using the
asyncio.run() or the
loop.run_until_complete() functions. The documentation suggests using
run() handles the setting and closing of the event loop object. The
run() command is actually just a wrapper around the
run_until_complete() command. For a more thorough explanation, I suggest reading this guide on
Runtime Error: Event Loop is closed Problem
Usually, this error can be fixed by replacing the
asyncio.run() command with the command
asyncio.new_event_loop().run_until_complete(). However, when used in conjunction with the
aiohttp library to make multiple API requests, that alternative will not work. This is due to multiple reasons. First, a TCP connector problem, second an SSL protocol problem, and thirdly an issue with the Proactor transport object. Let’s take a look at what the error logs for this problem may look like prior to the
RuntimeError: Event Loop is closed line.
Error Logs from the asyncio Library
Here is what the logs look like for this error:
Unclosed connector connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x00000254D4590280>, 25425.812)]'] connector: <aiohttp.connector.TCPConnector object at 0x00000254D4584730> Fatal error on SSL transport protocol: <asyncio.sslproto.SSLProtocol object at 0x00000254D459E1C0> transport: <_ProactorSocketTransport fd=916 read=<_OverlappedFuture cancelled>> … AttributeError: 'NoneType' object has no attribute 'send' Exception ignored in: <function _SSLProtocolTransport.__del__ at 0x00000254D4095E50> Traceback (most recent call last): … RuntimeError: Event loop is closed
Runtime Error: Event Loop is closed Solution
The problem with this error being raised isn’t so much that we can’t run the function. It’s more so we have an error exit code, can’t run multiple functions in sequence, and get yelled at by the command line. The
asyncio library not the most stable. So, this error is not too surprising, but you know what is surprising? This error has been around for a while. I found so many solutions on Stack Overflow that don’t work. Theoretically
run() should close the event loop gracefully. Gracefully means no errors. Let’s look at how we can change the source code to force a graceful shutdown of the function.
Edit the Source Code of the asyncio Library run Command Locally
How are we going to fix the error? We’re going to wrap a modification around the class for the
_ProactorBasePipeTransport’s delete method. This is the method that shuts down the event loop throwing the error. To do this, we’re going to import the
wraps annotation from
functools and the
asyncio.proactor_events. Technically we don’t have to import the Proactor class, but we’ll import for ease.
Let’s create our helper function to shut the interpreter up after we’ve already finished our loop. Our function will take one parameter, the function we’re wrapping. We’ll annotate a wrapper function that
wraps the passed in function parameter. The inner wrapper function will take itself as an argument, and any number of unnamed and named arguments.
All the wrapper function does is try to execute the function as normal, except when there’s a
RuntimeError, it’s not raised. After defining the functions, we’ll edit the
__del__ function of the Proactor object and set it to the silenced version. Now the closing of the loop will not raise errors in the console.
"""fix yelling at me error""" from functools import wraps from asyncio.proactor_events import _ProactorBasePipeTransport def silence_event_loop_closed(func): @wraps(func) def wrapper(self, *args, **kwargs): try: return func(self, *args, **kwargs) except RuntimeError as e: if str(e) != 'Event loop is closed': raise return wrapper _ProactorBasePipeTransport.__del__ = silence_event_loop_closed(_ProactorBasePipeTransport.__del__) """fix yelling at me error end"""
Summary fixing the
RuntimeError: Event Loop is closed asyncio Error
The problem we encountered was the program shutdown process raising an error when running
asyncio.run() on an async event loop when it shouldn’t have. The solution we implemented doesn’t directly solve the issue of the program not closing all its processes gracefully, but it does protect us from the problem. We directly imported the responsible object and wrote a wrapper around it with the
functools Python library. The wrapper function silences the
- Python Speech Recognition with SpeechRecognition Library
- Build Your Own AI Text Summarizer
- Web Scraping with Python Selenium and Beautiful Soup 4
- The Best Way to do Named Entity Recognition (NER)
- How to Send an Email with an Attachment in Python
I run this site to help you and others like you find cool projects and practice software skills. If this is helpful for you and you enjoy your ad free site, please help fund this site by donating below! If you can’t donate right now, please think of us next time.