Python Bug 修复案例分析:asyncio 事件循环异常引发的程序崩溃 两种修复方法

news2025/5/18 18:27:49

                 在 Python 异步编程的工作中,asyncio库为我们提供了高效处理并发任务的强大工具。然而,asyncio在使用过程中也可能因为一些细节处理不当而引发 Bug。下面,我们就来深入分析一个因asyncio事件循环异常导致程序崩溃的典型案例。兴趣的友友可以借鉴参考其中的修复步骤。​

bug案例背景​

      在前期开发的一个网络爬虫程序,利用asyncio实现异步请求网页,以提高爬取效率。代码大致如下:

import asyncio
import aiohttp


async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()


async def main():
    urls = ["https://example.com", "https://another-example.com", "https://yet-another-example.com"]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for result in results:
            print(result)


if __name__ == "__main__":
    main()

 

           上述代码的逻辑是创建多个异步任务,每个任务负责从一个指定的 URL 获取网页内容,然后通过asyncio.gather等待所有任务完成,并打印获取到的结果。然而,当运行这段代码时,程序抛出了异常:RuntimeError: This event loop is already running,并且程序崩溃。​

bug问题分析​

          异常信息解读:从RuntimeError: This event loop is already running异常提示可以看出,问题出在asyncio的事件循环上。asyncio通过事件循环来管理异步任务的执行,而这个错误表明我们在事件循环已经处于运行状态时,尝试进行了不恰当的操作。​

                错误根源探究:在 Python 中,asyncio默认使用一个全局的事件循环。在if __name__ == "__main__"语句块中直接调用main函数,而main函数是一个异步函数,它没有通过正确的方式与事件循环关联。正常情况下,我们需要通过asyncio.run函数来运行顶级异步函数,它会自动创建、管理和关闭事件循环。但在当前代码中,我们直接调用main,导致事件循环的管理出现混乱,进而引发了上述异常。​

bug修复过程​

       为了解决这个问题,我们需要正确地使用asyncio的事件循环来运行异步函数。有两种常见的修复方案:​

方案一:使用asyncio.run方式修复bug

import asyncio
import aiohttp


async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()


async def main():
    urls = ["https://example.com", "https://another-example.com", "https://yet-another-example.com"]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for result in results:
            print(result)


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

           在这个方案中,我们使用asyncio.run函数来运行main函数。asyncio.run会自动创建一个新的事件循环,运行传入的异步函数,并在函数执行完毕后关闭事件循环,从而避免了事件循环管理混乱的问题。再次运行程序,网页内容能够正常获取并打印,程序运行正常。​

方案二:手动管理事件循环方式修复

import asyncio
import aiohttp


async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()


async def main():
    urls = ["https://example.com", "https://another-example.com", "https://yet-another-example.com"]
    loop = asyncio.get_running_loop()
    async with aiohttp.ClientSession(loop=loop) as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for result in results:
            print(result)


if __name__ == "__main__":
    loop = asyncio.new_event_loop()
    try:
        asyncio.set_event_loop(loop)
        loop.run_until_complete(main())
    finally:
        loop.close()

             此方案中,我们手动创建一个新的事件循环,通过asyncio.set_event_loop将其设置为当前事件循环,然后使用loop.run_until_complete运行main函数,并在最后关闭事件循环。虽然这种方式相对复杂,但在一些特殊场景下,比如需要对事件循环进行更精细的控制时,会有其独特的优势。运行修改后的代码,同样能够顺利获取并打印网页内容,成功解决了问题。​

bug修复过程总结​

             通过这个asyncio事件循环异常的 Bug 修复案例,我们清晰地认识到在 Python 异步编程中,正确管理事件循环是确保程序稳定运行的关键。当遇到与asyncio相关的异常时,我们要仔细研读异常信息,结合asyncio的工作原理分析问题根源。无论是使用asyncio.run这种简洁的方式,还是手动管理事件循环,都需要遵循其规则和流程。在今后的异步编程实践中,我们应养成良好的编码习惯,提前规划好事件循环的使用方式,从而减少类似 Bug 的出现,充分发挥 Python 异步编程的高效优势。

 总之,Python Bug 的修复过程是一个不断学习和积累经验的过程。通过深入分析问题、选择合适的修复方法,并总结经验教训,我们能够不断提升自己的编程能力,编写出更加健壮、可靠的 Python 程序 。  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2378685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

题单:递归求和

宣布一个重要的事情,我的洛谷有个号叫 题目描述 给一个数组 a:a[0],a[1],...,a[n−1]a:a[0],a[1],...,a[n−1] 请用递归的方式出数组的所有数之和。 提示:递推方程 f(x)f(x−1)a[x]f(x)f(x−1)a[x]; 输入格式 第一行一个正整数 n (n≤100)n (n≤100)…

怎么在excel单元格1-5行中在原来内容前面加上固定一个字?

环境: WPS 2024 问题描述: 怎么在excel单元格1-5行中在原来内容前面加上固定一个字? 解决方案: 1.在Excel中,如果您想在单元格的内容前面添加一个固定的字,可以通过以下几种方法实现: 方法…

OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——mqtt库

准备工作 请依照这篇文章搭建环境 OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——环境配置_openharmony交叉编译-CSDN博客 下载 wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.5/gnutls-3.5.9.tar.xz 解压 tar -xf mkdir ./out cd ./out Cmake命…

数据结构 -- 顺序查找和折半查找

查找的基本概念 基本概念 查找:在数据集合中寻找满足某种条件的数据元素的过程 查找表(查找结构):用于查找的数据集合称为查找表,它由同一类型的数据结构元素(或记录)组成 关键字&#xff1…

信息收集+初步漏洞打点

目标:理解信息收集在渗透测试中的意义,熟悉常用工具用法,完成基本打点测试 一.理论学习: 模块内容说明信息收集分类主动信息收集 vs 被动信息收集目标发现子域名、IP、端口、子站点、目录、接口技术指纹识别Web框架(如…

JavaScript【5】DOM模型

1.概述: DOM (Document Object Model):当页面被加载时,浏览器会创建页面的文档对象模型,即dom对象;dom对象会被结构化为对象树,如一个HTML文档会被分为head,body等部分,而每个部分又…

Cloudflare防火墙拦截谷歌爬虫|导致收录失败怎么解决?

许多站长发现网站突然从谷歌搜索结果中“消失”,背后很可能是Cloudflare防火墙误拦截了谷歌爬虫(Googlebot),导致搜索引擎无法正常抓取页面。 由于Cloudflare默认的防护规则较为严格,尤其是针对高频访问的爬虫IP&…

如何在 Windows 11 或 10 的 CMD 中检查固件

检查 Windows 11 或 10 中现有设备的硬件固件版本,可以帮助用户安装和更新准确的驱动程序,进行故障排除活动,确保兼容性以及维护系统性能。因此,在本教程中,我们将讨论如何在命令提示符(CMD)中使用一些命令查找 Windows 服务器或桌面中硬件固件版本的方法。由于本教程将…

进阶-数据结构部分:3、常用查找算法

飞书文档https://x509p6c8to.feishu.cn/wiki/LRdnwfhNgihKeXka7DfcGuRPnZt 顺序查找 查找算法是指:从一些数据之中,找到一个特殊的数据的实现方法。查找算法与遍历有极高的相似性,唯一的不同就是查找算法可能并不一定会将每一个数据都进行访…

基于QT和FFmpeg实现自己的视频播放器FFMediaPlayer(一)——项目总览

在音视频开发的学习过程中,开发一款视频播放器是FFmpeg进阶的最好实战方法。本文将基于 QT 和 FFmpeg 着手实现自定义视频播放器 FFMediaPlayer,作为系列文章的开篇,我们先来整体了解项目的设计思路、架构与配置。 一、软件设计五大原则​ …

【HCIA】浮动路由

前言 我们通常会在出口路由器配置静态路由去规定流量进入互联网默认应该去往哪里。那么,如果有两个运营商的路由器都能为我们提供上网服务,我们应该如何配置默认路由呢?浮动路由又是怎么一回事呢? 文章目录 前言1. 网络拓扑图2. …

使用instance着色

本节我们学习使用instance着色器进行着色 //拾取var handler new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction(function(movement){console.log(movement);var pickedObject viewer.scene.pick(movement.position);if(Cesium.defined(picke…

【NLP 72、Prompt、Agent、MCP、function calling】

命运把我们带到哪里,就是哪里 —— 25.5.13 一、Prompt 1.User Prompt 用户提示词 当我们与大模型进行对话时,我们向大模型发送的消息,称作User Prompt,也就是用户提示词,一般就是我们提出的问题或者想说的话 但是我们…

Mysql数据库之集群进阶

一、日志管理 5.7版本自定义路径时的文件需要自己提前创建好文件,不会自动创建,否则启动mysql会报错 错误日志 rpm包(yum) /var/log/mysql.log 默认错误日志 ###查询日志路径 [rootdb01 ~]# mysqladmin -uroot -pEgon123 variables | grep -w log_e…

临床决策支持系统的提示工程优化路径深度解析

引言 随着人工智能技术在医疗领域的迅猛发展,临床决策支持系统(CDSS)正经历从传统规则引擎向智能提示工程的范式转变。在这一背景下,如何构建既符合循证医学原则又能适应个体化医疗需求的CDSS成为医学人工智能领域的核心挑战。本报告深入剖析了临床决策支持系统中提示工程的…

苹果新一代车载系统CarPlay Ultra来袭,全屏接管+ChatGPT助力,智能驾驶要“起飞”

AITOP100获悉,苹果又搞出大动作啦!正式推出了新一代车载系统——CarPlay Ultra。这次,苹果可是下了狠功夫,把iPhone和汽车的所有显示屏深度整合到了一起,还首次把ChatGPT引入到了驾驶体验当中。这系统可不简单&#xf…

无线信道的噪声与干扰

目录 1. 无线信道(wireless channel)与电磁波 2.1 电磁波的传输(无线信道传输) 2.2 视线(line of sight)传播与天线高度 2. 信道的数学模型 2.1 调制信道模型 2.1.1 加性噪声/加性干扰 2.1.2 乘性噪声/乘性干扰 2.1.3 随参信道/恒参信道 2.2 编码信道模型 2.3 小结 …

MySQL 8.0 OCP 1Z0-908 101-110题

Q101.which two queries are examples of successful SQL injection attacks? A.SELECT id, name FROM backup_before WHERE name‘; DROP TABLE injection; --’; B. SELECT id, name FROM user WHERE id23 oR id32 OR 11; C. SELECT id, name FROM user WHERE user.id (SEL…

BBR 的 buffer 动力学观感

这周很忙,今天还加了一天班,但还是抽空实现了五一在安徽泾县山区喝着一壶酒写的 BBR ProbeRTT 的想法,没多少行代码,它真就消除了带宽锯齿,皮了个鞋👞,昨天我还在群里说了今天再说说 BBR 的&…

Spring之Bean的初始化 Bean的生命周期 全站式解析

目录 导图 步骤 第一步 实例化 第二步 属性赋值 第三步 初始化 aware 接口 BeanPostProcessor 接口 InitializingBean 和 init-method 第四步使用 第五步使用后销毁 描述一下 Bean 的 生命周期 导图 步骤 总体上可以分为五步 首先是 Bean 的实例化Bean 在进行实例…