You have already called loop.close()
before you ran that sample piece of code, on the global event loop:
>>> import asyncio
>>> asyncio.get_event_loop().close()
>>> asyncio.get_event_loop().is_closed()
True
>>> asyncio.get_event_loop().run_until_complete(asyncio.sleep(1))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../lib/python3.6/asyncio/base_events.py", line 443, in run_until_complete
self._check_closed()
File "/.../lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
You need to create a new loop:
loop = asyncio.new_event_loop()
You can set that as the new global loop with:
asyncio.set_event_loop(asyncio.new_event_loop())
and then just use asyncio.get_event_loop()
again.
Alternatively, just restart your Python interpreter, the first time you try to get the global event loop you get a fresh new one, unclosed.
As of Python 3.7, the process of creating, managing, then closing the loop (as well as a few other resources) is handled for you when use asyncio.run()
. It should be used instead of loop.run_until_complete()
, and there is no need any more to first get or set the loop.
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 async
/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
run
vsloop.run_until_complete
commands - The Runtime Error: Event loop is closed Problem
- Error logs from the
asyncio
library
- Error logs from the
- The Runtime Error: Event loop is closed Solution
- Editing the Source Code of the
asyncio
library locally.
- 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()
over run_until_complete()
because 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 run()
vs run_until_complete()
.
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 _ProactorBasePipeTransport
from 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 RuntimeError
.
Further Reading
- 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.
Make a one-time donation
Your contribution is appreciated.
Donate
Make a monthly donation
Your contribution is appreciated.
Donate monthly
Make a yearly donation
Your contribution is appreciated.
Donate yearly
Problem Description
Aiohttp’s getting started entry case is written
import aiohttp
import asyncio
async def main():
async with aiohttp.ClientSession() as session:
async with session.get('https://python.org') as response:
print("Status:", response.status)
print("Content-type:", response.headers['content-type'])
html = await response.text()
print("Body:", html[:15], "...")
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Operation results
Status: 200
Content-type: text/html; charset=utf-8
Body: <!doctype html> ...
It seems that there is no problem, but after Python3.7, it has been improved, and it can be called directly.asyncio.run()
Execute the extension program without the operation of the underlying API such as an event loop loop, the above code
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Can be replaced directly
asyncio.run()
There is no problem in Linux and Mac, but running on Windows will report the following error.
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001B1FFE978B0>
Traceback (most recent call last):
File "D:DevToolsPythonlibasyncioproactor_events.py", line 116, in __del__
self.close()
File "D:DevToolsPythonlibasyncioproactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "D:DevToolsPythonlibasynciobase_events.py", line 746, in call_soon
self._check_closed()
File "D:DevToolsPythonlibasynciobase_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Cause Analysis
Third-party counterparts like AIOHTTP are dependent on standard library asyncio, and Asyncio has not been good for Windows. After Python 3.8, the event loop on the Windows system is used.ProactorEventLoop
(For Windows only) This document describes its defects under Windos:https://docs.python.org/zh-cn/3/library/asyncio-platforms.html#windows 👈
The function of causing an exception is_ProactorBasePipeTransport.__del__
Therefore, AiOHTTP iron is used to use _ProactorBasePiPipTransport, and it is automatically called when the program exits the memory.__del__
method
It is the above series of serial reactions to eventually throw RuntimeError: Event loop is closed
The general extension program does not use _ProactorBasePiPipetransport, so the following code can still run normally
import asyncio
async def main():
print('Hello...')
await asyncio.sleep(1)
print('...World')
asyncio.run(main())
I deliberately wrote a decorator to verify this:
import asyncio
from asyncio.proactor_events import _ProactorBasePipeTransport
from functools import wraps
def explicit_call(func):
@wraps(func)
def wrappers(self, *args, **kwargs):
print('call _ProactorBasePipeTransport.__del__')
return func(self, *args, **kwargs)
return wrappers
_ProactorBasePipeTransport.__del__ = explicit_call(_ProactorBasePipeTransport.__del__)
async def main():
print('Hello...')
await asyncio.sleep(1)
print('...World')
asyncio.run(main())
Normal execution, no use _ProactorBasepiPetransport
Hello...
...World
import asyncio
from asyncio.proactor_events import _ProactorBasePipeTransport
from functools import wraps
import aiohttp
async def main():
async with aiohttp.ClientSession() as session:
async with session.get('https://www.baidu.com') as response:
print("Status:", response.status)
print("Content-type:", response.headers['content-type'])
html = await response.text()
print("Body:", html[:15], "...")
def explicit_call(func):
@wraps(func)
def wrappers(self, *args, **kwargs):
print('call _ProactorBasePipeTransport.__del__')
return func(self, *args, **kwargs)
return wrappers
_ProactorBasePipeTransport.__del__ = explicit_call(_ProactorBasePipeTransport.__del__)
asyncio.run(main())
Printed firstcall _ProactorBasePipeTransport.__del__
Then report an error, the description is used _proactorbasepiPipetransport
Status: 200
Content-type: text/html
Body: <html>
...
call _ProactorBasePipeTransport.__del__
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001B11653EF70>
Traceback (most recent call last):
File "D:CodesSpiderProjectBingImageSpiderdemo.py", line 16, in wrappers
return func(self, *args, **kwargs)
File "D:DevToolsPythonlibasyncioproactor_events.py", line 116, in __del__
self.close()
File "D:DevToolsPythonlibasyncioproactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "D:DevToolsPythonlibasynciobase_events.py", line 746, in call_soon
self._check_closed()
File "D:DevToolsPythonlibasynciobase_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
The process has ended, exit the code is 0
solution
If you insist on continuing development under Windows, there have been these programs to choose
1. Do not use Run functions
Since _ProactorBasePiPipTransport will automatically turn off the event loop after the end, don’t use the Run function, use the official website, use loop.
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
2. Alternative event loops
Replace the default proactoreventloop as SelectoreventLoop before calling the Run function
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())
But SelectoreventLoop has some shortcomings, such as unsupported sub-process, etc.
3. Ignore the abnormality
This is a method of github on a foreign big . Using the decorator to ignore anomalies without changing the source code.
import asyncio
from asyncio.proactor_events import _ProactorBasePipeTransport
from functools import wraps
import aiohttp
async def main():
async with aiohttp.ClientSession() as session:
async with session.get('https://www.baidu.com') as response:
print("Status:", response.status)
print("Content-type:", response.headers['content-type'])
html = await response.text()
print("Body:", html[:15], "...")
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__)
asyncio.run(main())
More detailed information can be found on this Issue:https://github.com/aio-libs/aiohttp/issues/4324 👈
Related Links:
- https://github.com/aio-libs/aiohttp/issues/4324
- https://stackoverflow.com/questions/45600579/asyncio-event-loop-is-closed-when-getting-loop
- https://docs.python.org/zh-cn/3/library/asyncio-platforms.html#windows
- https://bugs.python.org/issue39232
If you like my article, welcomefocus on
👇like
👇Comment
👇collect
Thank you for your support! ! !
Currently learning about async, and it’s been a real challenge converting sync -> async. For example, the script below parses URLs from a text file, converts them into a list, then, using async, gets the status code of each URL and appends it next to the URL itself.
import requests, aiohttp, asyncio, re
apple = []
link = f"https://pastebin.com/raw/MW2KJNc3"
h = requests.get(link).text
urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', h)
for url in urls:
apple.append(f"{url}")
funny = []
async def get_pokemon(session):
resp = await session.get(url)
status_code = resp.status
funny.append((url, status_code))
async def main():
async with aiohttp.ClientSession() as session:
tasks = []
for url in apple:
tasks.append(asyncio.create_task(get_pokemon(session)))
original_pokemon = await asyncio.gather(*tasks)
for url, status_code in funny:
apple.append(f"{url} {status_code}")
asyncio.run(main())
Unfortunately though, I keep running into an error. How can I fix this RuntimeError: Event loop is closed error? Thank you!!
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000002A993A7B9A0>
Traceback (most recent call last):
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 116, in __del__
self.close()
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 745, in call_soon
self._check_closed()
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000002A993A7B9A0>
Traceback (most recent call last):
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 116, in __del__
self.close()
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 745, in call_soon
self._check_closed()
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000002A993A7B9A0>
Traceback (most recent call last):
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 116, in __del__
self.close()
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 745, in call_soon
self._check_closed()
File "C:UsersLopsidedAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Здраствуйте, недавно начал писать асинхронный парсер для cs money (только учусь программированию) и столкнулся с следующей ошибкой :
Код:
self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
<coroutine object ClientResponse.text at 0x000001B5F9DAAF80>
0.8101880550384521
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001B5F95232E0>
Traceback (most recent call last):
File "C:UsersKwuuuwhAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 116, in __del__
self.close()
File "C:UsersKwuuuwhAppDataLocalProgramsPythonPython310libasyncioproactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:UsersKwuuuwhAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 750, in call_soon
self._check_closed()
File "C:UsersKwuuuwhAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 515, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Собственно сам код:
Python:
from fake_useragent import UserAgent
import random
import asyncio
import aiohttp
import time
import json
data = []
async def get_html_data(url, session):
headers = {"user-agent": UserAgent().random}
async with session.get(url=url, headers=headers) as resp:
response = resp.text()
print(response)
async def create_task_html():
async with aiohttp.ClientSession() as session:
tasks = []
for offset in range(0, 2):
url = f'https://inventories.cs.money/5.0/load_bots_inventory/730?limit=32&offset={offset}&order=desc&priceWithBonus=30&sort=price&withStack=true'
task = asyncio.create_task(get_html_data(url, session))
tasks.append(task)
await asyncio.gather(*tasks)
def main():
start_time = time.time()
asyncio.run(create_task_html())
finish_time = time.time() - start_time
print(finish_time)
if __name__ == '__main__':
main()
Пытался решить проблему путём добавления в функцию main() за место asyncio.run(create_task_html()) следующую команду:
asyncio.get_event_loop().run_until_complete(create_task_html()) ,но в итоге в вывод идёт сначала:
Код:
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>nginx</center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>nginx</center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
после желаемый мне вывод и в заключении ошибка из начала
windows 10 pro
python — 3.10.5
aiohttp 3.7.4.post0
asyncio 3.4.3
Context
- Operating System: Windows 10
- Python Version: 3.9, 3.10
- aiogram version: 2.19, 3.0.0b2
- aiohttp version: 3.8.1
Expected Behavior
Process finishes gracefully
Current Behavior
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x00000207916D4040>
Traceback (most recent call last):
File "C:UsersuserAppDataLocalProgramsPythonPython39libasyncioproactor_events.py", line 116, in __del__
self.close()
File "C:UsersuserAppDataLocalProgramsPythonPython39libasyncioproactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:UsersuserAppDataLocalProgramsPythonPython39libasynciobase_events.py", line 746, in call_soon
self._check_closed()
File "C:UsersuserAppDataLocalProgramsPythonPython39libasynciobase_events.py", line 510, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Failure Information (for bugs)
Steps to Reproduce
import asyncio from aiogram import Bot TOKEN = "" # put your token here CHAT_ID = 0 # put your user ID here async def main(): bot = Bot(TOKEN) await bot.send_message(CHAT_ID, "Hello there!") await bot.session.close() # replace with `await bot.close()` on 2.x # await asyncio.sleep(0.1) if __name__ == '__main__': asyncio.run(main())
If you uncomment sleep
method, it works fine and finishes without traceback. I guess the problem is in aiohttp.
The message is delivered anyway, with or without sleep