0

0

Python 并发程序中的资源清理问题

冷漠man

冷漠man

发布时间:2026-01-30 08:01:02

|

443人浏览过

|

来源于php中文网

原创

asyncio.run() 中协程被取消时 finally 和 aexit 可能不执行,导致资源泄漏;应改用 create_task()+显式await、gather(return_exceptions=True)、定期检查取消标志、用shield保护关键清理,并验证第三方库的取消安全性。

python 并发程序中的资源清理问题

asyncio.run() 里没执行 finally 或 __aexit__ 怎么办

这是最常见的资源泄漏源头:用 asyncio.run() 启动协程时,如果协程被取消(比如 Ctrl+C、超时、任务异常退出),finally 块或异步上下文管理器的 __aexit__ 可能根本不会运行。

根本原因是 asyncio.run() 在遇到未处理的取消异常(CancelledError)时会直接终止事件循环,跳过协程的正常退出路径。

  • 别在顶层协程里依赖 finally 做清理 —— 改用 asyncio.create_task() + 显式 await task,并在外层加 try/except CancelledError
  • async with 时,确保上下文管理器本身在 __aexit__ 中处理了取消 —— 比如调用 await self._cleanup() 前加 if not task.cancelled():
  • 对关键资源(如数据库连接、文件句柄),在 __aexit__ 开头就记录日志,确认它是否被调用;若没日志,基本可断定被跳过了

多任务并发下 await asyncio.gather() 的 cleanup 陷阱

asyncio.gather() 默认行为是“任一子任务失败即取消其余”,但这个取消是静默的 —— 被取消的任务不会自动触发其内部的清理逻辑,除非你显式捕获并处理。

典型现象:启动 5 个数据库查询任务,第 3 个抛出 TimeoutError,其余 2 个还在跑,但 gather() 返回后它们就被丢弃了,连接没关,连接池慢慢耗尽。

立即学习Python免费学习笔记(深入)”;

  • 改用 asyncio.gather(*tasks, return_exceptions=True),拿到所有结果(含异常),再统一处理每个任务的清理
  • 每个子任务自己包装成独立函数,并在最外层加 try/finallyasync with —— 不要指望 gather() 替你兜底
  • 避免在 gather() 里传入已带 async with 的协程 —— 因为上下文管理器生命周期只绑定到该协程本身,不是整个 gather() 调用

信号处理(SIGINT/SIGTERM)与协程取消的时序错位

在生产环境用 uvicorn 或自建服务时,收到 SIGINT 后主协程被取消,但此时正在运行的子任务可能刚进入 I/O 等待,还没来得及响应取消信号,导致清理代码永远等不到执行机会。

行业贸易网站管理系统 2007 Beta 1
行业贸易网站管理系统 2007 Beta 1

1.修正BUG站用资源问题,优化程序2.增加关键词搜索3.修改报价4.修正BUG 水印问题5.修改上传方式6.彻底整合论坛,实现一站通7.彻底解决群发垃圾信息问题。注册会员等发垃圾邮件7.彻底解决数据库安全9.修改交易方式.增加网站担保,和直接交易两中10.全站可选生成html.和单独新闻生成html(需要装组建)11. 网站有10中颜色选择适合不同的行业不同的颜色12.修改竞价格排名方式13.修

下载

这不是 Python bug,而是异步取消的固有特性:取消只是设置一个标志,协程需主动检查(如通过 await asyncio.sleep(0) 或在 await 点响应)。

  • 在长循环中定期插入 if asyncio.current_task().cancelled(): break,尤其在 CPU 密集型处理段之后
  • asyncio.shield() 包裹真正不可中断的清理操作(如关闭 TCP 连接),防止它被外部取消打断
  • 注册信号处理器时,不要直接 loop.stop(),而应 asyncio.create_task(shutdown()),让 shutdown() 协程按需等待子任务完成

第三方库(如 httpx、aiomysql)的 async context manager 是否真可靠

很多库文档写着“支持 async with”,但实际实现里 __aexit__ 可能没处理 CancelledError,或者清理逻辑本身也 await 了不响应取消的底层调用(比如某些 SSL 关闭过程)。

验证方法很简单:手动取消任务,看连接是否从 netstat -an | grep :port 里消失,或观察连接池的 idle 数是否归零。

  • 优先选明确声明“cancel-safe cleanup”的库版本 —— 比如 httpx>=0.24.0 修复了 AsyncClient 在取消时可能卡住的问题
  • 对关键客户端,封装一层带超时的清理:用 asyncio.wait_for(self._client.aclose(), timeout=3.0)
  • 不要复用跨请求的 AsyncClient 实例做长期连接管理 —— 它的设计本意是短生命周期,长期持有反而增加清理不确定性

资源清理不是写完 async with 就万事大吉的事。异步取消的传播是协作式的,每个 await 点都可能是清理逻辑的断点。最容易被忽略的是:你以为在清理,其实协程早已被扔进垃圾堆,连入口函数都没走到。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

779

2023.08.22

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

118

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

258

2025.10.24

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

397

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

359

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2082

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

349

2023.08.31

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

9

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 815人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号