Python24_async with语法
Python24_async with 语法文章目录Python24_async with 语法[toc]1. 基础概念1.1 什么是 async with1.2 为什么需要 async with2. 核心原理2.1 异步上下文管理器协议2.2 执行流程3. 常见使用场景3.1 异步文件操作aiofiles3.2 异步数据库连接aiomysql/aiopg3.3 异步 HTTP 请求aiohttp3.4 异步锁asyncio.Lock4. 常见问题与解答QAQ1: async with 和 with 有什么区别Q2: 如何自定义异步上下文管理器Q3: async with 可以嵌套使用吗Q4: __aexit__ 的参数是什么意思Q5: 可以在 async with 中使用 await 吗Q6: 如何正确处理异常Q7: 异步上下文管理器在 __aexit__ 中可以再使用 await 吗5. 最佳实践5.1 使用 asynccontextmanager 简化代码5.2 超时控制5.3 避免常见错误6. 速查表7. 相关知识点延伸1. 基础概念1.1 什么是async withasync with是 Python 异步上下文管理器Asynchronous Context Manager的语法糖用于在异步代码中管理资源的获取和释放。asyncwith表达式as变量:# 异步代码块pass1.2 为什么需要async with场景普通withasync with文件操作同步✅ 适用❌ 不适用异步数据库连接❌ 阻塞✅ 非阻塞异步网络请求❌ 阻塞✅ 非阻塞异步锁Lock❌ 阻塞✅ 非阻塞2. 核心原理2.1 异步上下文管理器协议一个对象要成为异步上下文管理器必须实现以下两个异步方法classAsyncContextManager:asyncdef__aenter__(self):进入上下文时调用returnselfasyncdef__aexit__(self,exc_type,exc_val,exc_tb):退出上下文时调用# 处理异常或清理资源pass2.2 执行流程┌─────────────────┐ │ async with │ │ 表达式 as x: │ └────────┬────────┘ ▼ ┌─────────────────┐ │ await __aenter__() │ ← 异步获取资源 │ 返回值赋给 x │ └────────┬────────┘ ▼ ┌─────────────────┐ │ 执行代码块 │ └────────┬────────┘ ▼ ┌─────────────────┐ │ await __aexit__() │ ← 异步释放资源 │ (无论是否异常都执行) │ └─────────────────┘3. 常见使用场景3.1 异步文件操作aiofilesimportaiofilesimportasyncioasyncdefread_file():asyncwithaiofiles.open(data.txt,r)asf:contentawaitf.read()print(content)asyncio.run(read_file())3.2 异步数据库连接aiomysql/aiopgimportaiomysqlasyncdefquery_db():asyncwithaiomysql.create_pool(hostlocalhost,userroot,passwordpwd,dbtest)aspool:asyncwithpool.acquire()asconn:asyncwithconn.cursor()ascur:awaitcur.execute(SELECT * FROM users)resultawaitcur.fetchall()returnresult3.3 异步 HTTP 请求aiohttpimportaiohttpimportasyncioasyncdeffetch_url(url):asyncwithaiohttp.ClientSession()assession:asyncwithsession.get(url)asresponse:returnawaitresponse.text()# 使用htmlasyncio.run(fetch_url(https://api.github.com))3.4 异步锁asyncio.Lockimportasyncio lockasyncio.Lock()counter0asyncdefincrement():globalcounterasyncwithlock:# 确保同一时间只有一个协程修改 countercurrentcounterawaitasyncio.sleep(0.1)# 模拟耗时操作countercurrent1asyncdefmain():awaitasyncio.gather(*[increment()for_inrange(10)])print(fCounter:{counter})# 输出: Counter: 10asyncio.run(main())4. 常见问题与解答QAQ1:async with和with有什么区别答特性withasync with方法__enter__/__exit____aenter__/__aexit__调用方式同步调用需要await使用场景同步资源管理异步资源管理性能阻塞非阻塞可并发错误示例# ❌ 错误在异步函数中使用同步 with 管理异步资源asyncdefwrong():withaiohttp.ClientSession()assession:# 错误passQ2: 如何自定义异步上下文管理器答方式一类实现classAsyncDatabase:asyncdef__aenter__(self):self.connawaitcreate_connection()returnself.connasyncdef__aexit__(self,exc_type,exc,tb):awaitself.conn.close()# 返回 True 表示异常已处理不再传播returnFalse# 使用asyncwithAsyncDatabase()asconn:awaitconn.query(SELECT 1)方式二装饰器asynccontextmanagerfromcontextlibimportasynccontextmanagerasynccontextmanagerasyncdefmanaged_resource():print(获取资源...)resourceawaitcreate_async_resource()try:yieldresourcefinally:print(释放资源...)awaitresource.cleanup()# 使用asyncwithmanaged_resource()asres:awaitres.do_something()Q3:async with可以嵌套使用吗答可以支持多种写法# 方式一嵌套asyncwithA()asa:asyncwithB()asb:pass# 方式二单行Python 3.10asyncwithA()asa,B()asb:pass# 方式三括号Python 3.10推荐asyncwith(A()asa,B()asb,C()asc):passQ4:__aexit__的参数是什么意思答asyncdef__aexit__(self,exc_type,exc_val,exc_tb): exc_type: 异常类型如 ValueError exc_val: 异常实例 exc_tb: 异常追踪信息 ifexc_typeisnotNone:print(f发生异常:{exc_val})# 返回 True 会抑制异常False 或 None 会传播异常returnTrue示例classSuppressError:asyncdef__aenter__(self):returnselfasyncdef__aexit__(self,exc_type,exc_val,exc_tb):ifexc_typeValueError:print(f捕获 ValueError:{exc_val})returnTrue# 抑制异常returnFalse# 其他异常正常抛出asyncdeftest():asyncwithSuppressError():raiseValueError(测试错误)# 被捕获不会抛出print(继续执行)Q5: 可以在async with中使用await吗答可以而且这是常态asyncdefprocess():asyncwithget_session()assession:resultawaitsession.fetch_data()# ✅ 正常awaitsession.save(result)# ✅ 正常Q6: 如何正确处理异常答classSafeAsyncContext:asyncdef__aenter__(self):returnselfasyncdef__aexit__(self,exc_type,exc_val,exc_tb):# 清理资源无论是否异常都会执行awaitself.cleanup()# 选择是否处理异常ifexc_typeisasyncio.CancelledError:returnTrue# 抑制取消异常returnFalse# 其他异常继续传播# 外部捕获asyncdefmain():try:asyncwithSafeAsyncContext():raiseValueError(测试)exceptValueError:print(捕获到 ValueError)Q7: 异步上下文管理器在__aexit__中可以再使用await吗答可以这是设计用途之一classAsyncConnection:asyncdef__aexit__(self,exc_type,exc_val,exc_tb):# 异步关闭连接awaitself.conn.close()# 异步记录日志awaitlog_async(连接已关闭)# 异步发送指标awaitmetrics.send(connection_closed)5. 最佳实践5.1 使用asynccontextmanager简化代码fromcontextlibimportasynccontextmanagerasynccontextmanagerasyncdeftransaction(db):awaitdb.begin()try:yielddbawaitdb.commit()exceptException:awaitdb.rollback()raise# 使用asyncwithtransaction(database)asdb:awaitdb.execute(INSERT ...)5.2 超时控制importasyncioasyncdefwith_timeout():try:asyncwithasyncio.timeout(5):# Python 3.11asyncwithaiohttp.ClientSession()assession:asyncwithsession.get(https://slow.com)asresp:returnawaitresp.text()exceptasyncio.TimeoutError:print(请求超时)5.3 避免常见错误# ❌ 错误忘记 awaitasyncwithsome_async_context():# 正确passwithsome_async_context():# 错误协程没有被 await# ❌ 错误在同步函数中使用 async withdefsync_function():asyncwithsomething():# 错误同步函数不能有 awaitpass# ✅ 正确使用 asyncio.run 或 awaitasyncdefasync_function():asyncwithsomething():pass6. 速查表需求代码示例创建异步上下文管理器实现__aenter__和__aexit__简化创建使用asynccontextmanager多个资源async with A() as a, B() as b:异常处理在__aexit__中判断exc_type抑制异常__aexit__返回True超时控制async with asyncio.timeout(10):7. 相关知识点延伸async for- 异步迭代器asyncio.gather()- 并发执行多个协程asyncio.create_task()- 创建后台任务contextlib.AsyncExitStack- 动态管理多个异步上下文
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2523558.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!