Bootstrap

python协程:RuntimeError: Event loop is closed解决办法

1、先上bug代码:

import asyncio
import aiohttp
urls = [
    "https://tenfei03.cfp.cn/creative/vcg/800/new/VCG211224199769.jpg",
    "https://alifei03.cfp.cn/creative/vcg/800/new/VCG211226914371.jpg",
    "https://tenfei02.cfp.cn/creative/vcg/800/new/VCG211188068441.jpg"
]

async def aiodownload(url):

    name = url.rsplit("/", 1)[1]  # 从右边切,切一次,得到[1]位置的内容
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            # 返回请求,写入数据
            with open(name, mode="wb") as f:  # 创建文件
                f.write(await resp.content.read())   # 读取内容是异步的需要在前面加上await  content读图片
                print(name,"下载成功")

async def main():
    tasks = []
    for url in urls:
        tasks.append(asyncio.create_task(aiodownload(url)))
    await asyncio.wait(tasks)

if __name__ == '__main__':
    asyncio.run(main())

2、run后会报出错误(RuntimeError: Event loop is closed):

 3、解决方法:在调用 run 函数前,替换默认的 ProactorEventLoop 为 SelectorEventLoop

    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    asyncio.run(main())

4、原因分析:

像 aiohttp 这类第三方协程库都是依赖于标准库 asyncio 的,而 asyncio 对 Windows 的支持本来就不好。Python3.8 后默认 Windows 系统上的事件循环采用 ProactorEventLoop (仅用于 Windows )这篇文档描述了其在 Windows 下的缺陷:https://docs.python.org/zh-cn/3/library/asyncio-platforms.html#windows 
引发异常的函数是 _ProactorBasePipeTransport.__del__ ,所以 aiohttp 铁定使用了 _ProactorBasePipeTransport,并且在程序退出释放内存时自动调用了其__del__ 方法

;