aiohttp学习笔记及RuntimeError: Event loop is closed解决办法(close问题)

playwright报错:“Event loop is closed! Is Playwright already stopped?” 解决playwright报错 阅读详情

aiohttp学习笔记及RuntimeError: Event loop is closed解决办法(close问题)

一、概念

1.爬虫的基本组成
	a.url管理模块
	b.HTML下载模块
	c.数据存储模块
	d.爬虫调度模块
2.同步和异步
	同步和异步关注的是消息通信机制
	
	同步:再发出一个调用时,在没有得到结果之前,该调用就不会返回,但是一旦调用返回,就得到返回值。换句话说,就是由调用者主动等待这个调用结果
	
	异步:调用在发出之后,这个调用就直接返回了,所以没有返回结果。当一个异步过程调用发出之后,调用者不会立刻得到结果,而是再在调用发出后,被调用这通过状态、通知来通知调用者,或通过回调函数处理这个调用
3.阻塞与非阻塞
	阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态
	阻塞调用是指调用结果返回之前,当前线程会被挂起
	调用线程只有在得到结果之后才会返回
	非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程 
4.协程
	coroutines:一种比线程更加轻量级的存在,一个线程拥有多个协程。
	协程被操作系统内核管理,完全可以自由程序控制,这样就是在性能上得到了很大的提升,因为单线程所以避免了上下文之间的切换
	通过yield/send可以实现一个协程,yield可以让协程暂停和线程的阻塞是有本质的却别,协程暂停完全由程序控制,线程的阻塞状态由操作系统内核控制。开销远小于线程。python3.5以后 async/await成为了更好的替代方案
5.asyncio
	一个异步io库,从python3.4开始加入官方库,一直到python3.5才将许多临时api定格下来,知道python3.6才定格,python3.6为其加入async和await两大关键字,到python3.7加入asyncio.run方法,进一步简化运行入口的写法
6.事件循环
	事件循环是一种处理多并发量的有效方式,在维基百科中它被描述为“一种等待程序分配事件或消息的变成架构”,我们可以定义事件循环来简化使用轮询方法来监控时间。他的意义最通俗的说法是“当A发生时,执行B”。他是asyncio提供的“中央处理设备”
7.uvlop
	Cypthon编写、用来代替asyncio事件循环。
	作者说“他在速度上至少比NOde.js、geven以及其他任何python异步框架快2倍”
8.其他
	mongodb的异步版本 Motor
	mongodb文件存储系统 GridFS

GridFS:https://blog.youkuaiyun.com/u011194506/article/details/75578818?utm_medium=distribute.pc_relevant.none-task-blog-searchFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-searchFromBaidu-1.control

二、示例代码

1.aiohttp
import asyncio
import aiohttp


# 这里加异常捕获是因为uvloop不支持windos环境
try:
    import uvloop
    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError as e:
    pass
url = "http://www.baidu.com"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/88.0.4324.104 Safari/537.36",
}


async def fetch(url):
    timeout = aiohttp.ClientTimeout(total=5)
    
    #  tc为一个connector          限制TCP的连接数 忽略SSL证书错误
    async with aiohttp.TCPConnector(limit=30, verify_ssl=False)as tc:
        
        #  定义一个session,通过异步上下文关键字定义
        async with aiohttp.ClientSession(connector=tc,timeout=timeout)as session:
            # req就是response
            async with session.get(url, headers=headers)as req:
                status = req.status
                if status in [200, 201]:
                    
                    # 因为异步所以需要用await去调用
                    source = await req.text()
                    print(source)
                    return source


if __name__ == '__main__':
    # 创建一个事件循环a
    loop = asyncio.new_event_loop()
    
    asyncio.set_event_loop(loop)
    loop = asyncio.get_event_loop()
    tasks = [asyncio.ensure_future(fetch(url)) for i in range(10)]
    loop.run_until_complete(asyncio.wait(tasks))
    # loop.run_until_complete(asyncio.sleep(0))
    loop.close()
2.aiohttp添加socks代理

pip install aiohttp-socks

from aiohttp_socks import SocksConnector
async with semaphore:
    async with aiohttp.ClientSession(connector=SocksConnector.from_url(proxies) if proxies else None) as session:
        async with session.get(url, headers=headers, allow_redirects=True, timeout=20) as response:
            content, text = await response.read(), await response.text("utf-8","ignore")
            status_code = response.status
            response_headers = dict(response.headers)
            reason = response.reason
            return url, status_code, response_headers, content, text, reason

这里之前使用的是SocksConnector,但会出现错误(没有看具体原因),后来改用ProxyConnector

from aiohttp_socks import SocksConnector, ProxyConnector
    async with aiohttp.ClientSession(connector=ProxyConnector.from_url(proxy) if proxy else None) as session:
3.百度文库列表页代码示例
import asyncio
import time
import aiohttp
import requests
import html
import logging.config
from new.log_config import log_conf
from lxml import etree
# 使用SocksConnector会存在某些问题
from aiohttp_socks import SocksConnector, ProxyConnector
from queue import Queue
from fake_useragent import UserAgent

# log
logging.config.dictConfig(log_conf)
logger = logging.getLogger("buggy")

session = requests.session()

proxy = '这里是socks5代理'

ua_sum = UserAgent()
ua = ua_sum.random
headers = {
    "User-Agent": ua,
    "Cookie": 'BAIDUID=1233:FG=1; Hm_lpvt_={}'.format(int(time.time())),
}
# 获取到的数据直接放到队列里
page_list_queue = Queue()


async def get_list_url(keyword, pagenum):
    url_list = []
    for num in range(pagenum):
        number = num * 10
        url = f"https://wenku.baidu.com/search/main?word={keyword}" \
              f"&org=0&fd=0&lm=0&od=0&ie=gbk&fr=top_home&pn={number}"
        url_list.append(url)
    return url_list


async def listpage_request(session, url):
    async with session.get(url=url, headers=headers, verify_ssl=False, timeout=10) as res:
        response_text = await res.text("gbk", errors="ignore")
        await deal_listpage(response_text)


async def deal_listpage(response_text):
    serch_html = etree.HTML(response_text)
    serch_list = serch_html.xpath("//div[@class='main']/div[@class='search-result']/dl")
    for li in serch_list:
        tag_str = etree.tostring(li, method='html').decode()
        tag_html = html.unescape(tag_str)
        tag_html.replace('<em>', '').replace('</em>', '')
        li = etree.HTML(tag_html)

        # title
        title = li.xpath(".//dt/p[1]/a/@title")[0]
        # url
        url = li.xpath(".//dt/p[1]/a/@href")[0]
        # 来源网站 source_web
        source_web = "百度文库"
        # 描述 describe
        describe_tag = li.xpath('.//div[@class="summary-box fl"]/p[@class="summary lh21"]')[0]
        describe_str = etree.tostring(describe_tag, method='html').decode("utf8", "ignore")
        describe_html_str = html.unescape(describe_str)
        describe = describe_html_str[24:-5].replace('<em>', '').replace('</em>', '')
        data = {
            "title": title,
            "source_web": source_web,
            "describe": describe,
            "details_url": url,
        }
        page_list_queue.put(data)


async def get_list_page(keyword):
    url_list = await get_list_url(keyword, 77)
    async with aiohttp.ClientSession(connector=ProxyConnector.from_url(proxy) if proxy else None) as session:
        tasks = [asyncio.create_task(listpage_request(session, url)) for url in url_list]
        await asyncio.wait(tasks)


def baidu_list_main(keyword):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(get_list_page(keyword))
    data_list = []
    while page_list_queue.empty() is not True:
        data = page_list_queue.get()
        data_list.append(data)
    return {"keyword": keyword, "return_size": len(data_list), "return_list": data_list}


if __name__ == '__main__':
    start = time.time()
    print(baidu_list_main("的"))
    print(time.time() - start)

三、踩过的坑

代码完全没有问题(参考示例代码1),但会报RuntimeError: Event loop is closed

如果把close注释掉,就不会出现这个问题,大佬(感谢博文大佬,本次关于aiohttp得学习完全靠博文大佬得支持)告诉我在实际开发中大部分也是不用close的,如果close必须,参考:https://github.com/aio-libs/aiohttp/issues/4324#issuecomment-733884349

解决办法:(重写close中的方法)

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__)
Python asyncio 入门:从伪异步到真正高并发的实战指南 asyncio 是 Python 实现高并发 I/O 密集型任务的核心机制,其本质是基于单线程事件循环的协作式调度系统,通过协程让渡(await)实现毫秒级多路复用。它不改变 CPU 执行模型,但彻底重构了 IO 等待期间的资源利用逻辑——当网络请求阻塞时,CPU 可立即切换处理其他就绪任务,从而将服务器并发能力从千级线程提升至十万级连接。技术价值在于极低的内存开销与确定性的调度延迟,广泛应用于 Web 服务(如 FastAPI)、爬虫、实时通信和微服务网关等场景。本文聚焦 asyncio 的真实落地,直击 阅读详情

相关推荐

Python异步编程实战:从协程原理到高并发爬虫落地

异步编程是一种面向I/O密集型任务的并发模型,其核心在于事件循环驱动的协程调度机制,通过非阻塞等待实现单线程内高效复用CPU资源。相比多线程,它规避了GIL限制与上下文切换开销,特别适用于Web API、网络爬虫、实时数据采集等场景。技术价值体现在数量级性能提升——如QPS翻倍、响应时间压至毫秒级,且内存占用极低。典型应用包括高并发HTTP请求(aiohttp)、异步数据库操作(aiosqlite)及带限速/重试的健壮采集系统。本文聚焦async/await语法本质、事件循环工作原理与生产级异步实践,直击协

aiman5818的博客 368

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

在学习协程时,用asyncio.run()运行会出现一下RuntimeError: Event loop is closed,如下 解决办法:将 asyncio.run(main())替换为下面两行 loop = asyncio.get_event_loop() loop.run_until_complete(main()) 总而言之是asyncio.run()会自动关闭循环,并且调用_ProactorBasePipeTransport.__del__报错, 而asyncio.run_un.

weixin_46830352的博客 1万+

pytest-asyncio异步测试实战:从原理到避坑指南

在Python异步编程中,单元测试是确保代码质量的关键环节。asyncio作为异步编程的核心库,其事件循环机制要求测试框架能够正确处理协程的调度与执行。pytest作为主流的测试框架,通过pytest-asyncio插件实现了与异步代码的无缝集成,解决了协程未被等待、事件循环管理等核心问题。这一技术组合为微服务、数据管道等高性能应用提供了可靠的测试保障。本文聚焦pytest-asyncio在实际工程中的应用,针对异步固件管理、混合代码调用、超时竞态条件等高频痛点,结合事件循环和协程调度原理,提供经过验证的解

weixin_34377919的博客 310

【ERROR】asyncio.run(main())报错:RuntimeError: Event loop is closed

asyncio.run(main())报错:RuntimeError: Event loop is closed DeprecationWarning: There is no current event loop loop = asyncio.get_event_loop()

weixin_44624036的博客 2179

Python异步测试实战:pytest-asyncio从入门到精通

异步编程是现代软件开发中提升性能的关键技术,其核心原理基于事件循环和协程调度机制。通过事件循环管理异步任务,开发者能够高效处理I/O密集型操作,避免线程阻塞带来的性能损耗。这一技术价值在于显著提升应用吞吐量和响应速度,广泛应用于网络服务、数据爬虫和实时通信等场景。在Python生态中,pytest-asyncio插件为异步代码测试提供了专业解决方案,它通过自动管理事件循环生命周期,支持异步fixture和AsyncMock等高级特性,帮助开发者构建健壮的测试体系。掌握异步测试技巧能有效发现任务泄露和竞态条件

weixin_33816821的博客 390

【Python自学笔记】asyncio.run()报错RuntimeError:Event loop is closed的原因以及解决办法

asyncio.run()报错RuntimeError:Event loop is closed的原因以及解决办法

XiaoqiangClub的博客 5913

【Python】aiohttp库报错:raise RuntimeError(‘Event loop is closed‘) RuntimeError: Event loop is closed

【Python】aiohttp库报错:raise RuntimeError('Event loop is closed') RuntimeError: Event loop is closed

MZH 1626

Windows下QT5.15.2安装MQTT模块全攻略(附分支选择避坑指南)

本文详细介绍了在Windows环境下为QT5.15.2安装MQTT模块的完整流程,包括环境准备、源码获取、编译配置及项目集成等关键步骤。特别针对分支选择、依赖项处理和常见错误提供了实用解决方案,帮助开发者高效完成MQTT模块的安装与调试,适用于物联网开发场景。

weixin_29224589的博客 466

aiohttp出现 raise RuntimeError(‘Event loop is closed‘) 来自(<function _ProactorBasePipeTransport.__del_)

Python3.8 后默认 Windows 系统上的事件循环采用 ProactorEventLoop (仅用于 Windows )这篇文档描述了其在 Windows 下的缺陷:https://docs.python.org/zh-cn/3/library/asyncio-platforms.html#windows 👈。这是 Github 上一个外国大佬的方法,在不改变源码的前提下,使用装饰器忽略掉异常。过来了:(如有侵权或者不舒服,可联系我撤下,狗头保命),所以 aiohttp 铁定使用了。

peanutfish的专栏 1489

脑机接口(BCI)从原理到开发实战 01|意念控制真的来了?一文看懂脑机接口的技术革命

类型定义典型应用主动式用户主动产生特定思维模式来控制设备运动想象(想象左手/右手移动)反应式用户被动接受外部刺激,系统检测大脑反应P300拼写器、SSVEP(稳态视觉诱发电位)被动式系统监测用户自发脑状态,不要求主动控制疲劳监测、情绪识别、注意力评估本系列后续文章将重点围绕主动式(运动想象)和反应式(P300/SSVEP)展开实战。脑机接口,这个曾经只存在于科幻中的概念,正在政策、资本、技术的三重驱动下,加速从实验室走向产业落地。2026年,注定是脑机接口发展史上浓墨重彩的一年。

小明的博客 1431

Tomcat启动过程中cmd窗口(控制台)中文乱码的问题

tomcat启动时,启动过程日志中文乱码的处理方法。

寻码启示 1942

【Python】raise RuntimeError(‘Event loop is closed‘) RuntimeError: Event loop is closed

aiohttp 这类第三方协程库依赖于标准库 asyncio , asyncio 对 Windows 的支持不好(不是主要的目标对象)。Python3.8 后默认 Windows 系统上的事件循环采用 ProactorEventLoop (仅用于 Windows )转载原文链接:https://blog.youkuaiyun.com/u011027547/article/details/129775955。在run之前设置set_event_loop_policy适配windows。

u010478658的专栏 878

一键转换B站M4S缓存为MP4:无需FFMPEG命令的简易工具

本文介绍了一款专为B站用户设计的绿色工具,可将缓存的M4S视频和音频文件一键转换为通用MP4格式。该工具完全图形化操作,无需学习复杂的FFmpeg命令,解决了普通用户处理B站缓存视频的痛点。文章详细讲解了从下载、配置到转换的完整流程,并提供了常见问题排查与安全使用建议,帮助用户高效、安全地管理离线视频内容。

joy55的博客 480

python3从入门到精通(七): 异步HTTP框架之aiohttp模块

aiohttp是Python基于asyncio的异步HTTP框架,包含异步HTTP客户端和服务器功能。其核心优势在于异步非阻塞,适合高并发网络请求和IO密集型Web应用。HTTP客户端通过ClientSession管理会话,支持连接池复用、全局配置(headers/cookies/timeout等)和精细超时控制。关键注意事项包括:避免同步阻塞调用、复用ClientSession、完善异常处理、必须配置超时。

zkcJava的博客 1130

PointNet++改进策略目录

后续我将如何使用文章中创新点加入的PointNet++中代码实现部分进行更新。

u012901740的博客 2195

42页Claude 3技术报告解读(Opus, Sonnet, Haiku)

在Claude 3模型中,增加了一个额外的原则到Claude的宪法中,以鼓励尊重残疾人权利,这一原则源自对集体宪法AI的研究。Claude 3模型的训练基于专有的混合数据集,包括截至2023年8月互联网上公开可用的信息,以及第三方提供的非公开数据、数据标注服务和付费承包商提供的数据,还有内部生成的数据。这些初始响应通常包含有害和有毒的内容。Claude 3模型家族在推理、编码和问答任务上展现出卓越的性能,特别是在行业标准基准测试中取得了显著的提升,证明了其在处理复杂问题和提供准确答案方面的能力。

具身机器人和通用AI 2432

Python异步HTTP编程实战:aiohttp核心原理与高并发应用开发指南

异步编程是现代高性能网络应用的核心技术,它通过事件循环和协程机制,解决了传统同步I/O模型中的阻塞问题,从而大幅提升资源利用率和系统吞吐量。其技术价值在于能够以少量线程处理海量并发连接,特别适合高并发的网络爬虫、实时API服务和微服务网关等场景。在Python生态中,aiohttp作为基于asyncio的异步HTTP框架,通过非阻塞的客户端和服务器实现,为开发者提供了构建高效网络应用的有力工具。本文结合网络爬虫和Web服务器等高频应用场景,深入解析aiohttp的会话管理、连接池优化和并发控制等核心机制,帮

weixin_33951761的博客 383

华为OD面试八股真题 - 操作系统 - 1

华为OD技术面,操作系统相关八股真题提供详细解答,这篇博客主要涉及于进程和线程相关知识点

qq_45776114的博客 1633

python3从入门到精通(五): python协程之asyncio模块(异步IO)(一)

Python的asyncio是一个异步I/O框架,通过单线程实现并发执行,特别适合I/O密集型场景。其核心原理为"事件循环+协程"模式:协程是可暂停/恢复的函数,由async def定义;await关键字用于暂停当前协程并将控制权交还事件循环;事件循环则负责调度任务队列、监听I/O事件并切换协程执行。asyncio还提供async with实现异步上下文管理,确保资源正确释放。整体采用非阻塞I/O和事件驱动机制,避免了多线程的上下文切换开销,使单线程能高效处理大量并发I/O操作。

zkcJava的博客 924

RH850从0搭建Autosar开发环境【23】- Davinci Configurator之DCM实操实现DID的读取写入

RH850从0搭建Autosar开发环境【23】- Davinci Configurator之DCM实操实现DID的读取写入,结合Developer实现

weixin_42412049的博客 1809

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Python异步Web性能优化:事件循环、连接池与CPU隔离实战

异步I/O是现代Web服务高性能的核心机制,其本质是基于事件循环的协作式调度模型,通过让出控制权实现高并发下的资源复用。理解async/await并非语法糖,而是对非阻塞执行路径的显式声明;掌握数据库连接池、HTTP客户端超时矩阵、文件IO线程池等资源调度策略,可避免连接饥饿、超时级联与事件循环饿死等典型故障。技术价值在于以单线程高效承载数千并发,显著降低延迟与CPU开销。广泛应用于FastAPI、Uvicorn等异步框架的SaaS后台、微服务网关及实时API服务。本文聚焦asyncpg、httpx.Asy

weixin_30516243的博客 347

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Python异步测试事件循环冲突:pytest-asyncio问题诊断与解决方案

在Python异步编程中,事件循环是协程调度的核心机制,它管理着异步任务的执行顺序和状态转换。其工作原理基于事件驱动模型,通过事件队列和回调机制实现非阻塞I/O操作。理解事件循环的生命周期管理对于构建稳定的异步应用至关重要,能有效避免资源泄漏和状态污染。在软件测试领域,这一技术价值尤为突出,特别是在单元测试和集成测试场景中,确保测试环境的隔离性和可重复性是保证代码质量的关键。当使用pytest-asyncio进行异步测试时,开发者常会遇到事件循环冲突问题,表现为'RuntimeError: This eve

weixin_34364071的博客 449

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Python异步测试实战:pytest-asyncio核心原理与最佳实践

在Python异步编程中,事件循环是驱动协程执行的核心机制,它通过非阻塞I/O调度实现高并发处理。理解asyncio的工作原理是编写高效异步代码的基础,其技术价值在于能够显著提升I/O密集型应用的吞吐量和资源利用率,广泛应用于Web服务、网络爬虫、实时数据处理等场景。针对异步代码的测试挑战,pytest-asyncio插件通过无缝集成pytest框架与asyncio事件循环,解决了异步函数在传统测试框架中无法直接执行的问题。该插件利用pytest的钩子系统自动管理事件循环生命周期,支持异步夹具和并发测试,并

479

Python异步编程实战:从原理到Hacker News爬虫

Python异步编程是一种面向I/O密集型任务的并发执行模型,其核心在于协程与事件循环协同工作,避免线程阻塞,将等待时间转化为有效吞吐。它并非语法糖,而是对传统同步执行流的重构,适用于HTTP请求、数据库访问、文件读写等典型外部交互场景。相比多线程/多进程,asyncio以极低开销实现高并发,尤其在API调用、爬虫、微服务通信中显著降低响应延迟、提升资源利用率。本文结合Hacker News开放API,详解async/await机制、aiohttp连接复用、aiosqlite异步存储及限流熔断等生产级实践,

weixin_33985507的博客 371

为什么无名杀网页版值得你花5分钟:3个免费开局的理由

无名杀网页版是一款免费开源的在线三国杀游戏,浏览器打开就能玩。不用下载、不用安装,内置数百名三国武将和十几种游戏模式,单机、联机、自定义玩法全都有。 [![免费开源的无名杀网页版启动画面](https://raw.gitcode.com/GitHub_Trending/no/noname/raw/e18a8256e01ab1357e4c7472349dceb3d0aa1a3a/image/bac

gitblog_01128的博客 338
上一篇: Pycharm及pycharm的terminal运行与CMD运行不一致,出现中文转英文问题(或英文转中文)
下一篇: 解决xadmin.add_tab添加新标签页时,需要刷新整个页面才能显示问题
L_W_D_
博客等级 码龄7年 8粉丝 13原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值