编程Python开发者(asyncio/后端)

什么是Python中的异步上下文管理器(async context manager),如何实现它,以及它在哪些情况下是不可或缺的?

用 Hintsage AI 助手通过面试

答案。

异步上下文管理器是一个定义了异步方法__aenter____aexit__的对象,并在async with结构中使用。这样的管理器用于在异步函数中正确地打开/关闭资源:数据库连接、文件、会话等。

实现示例:

class AsyncDBConnection: async def __aenter__(self): self.conn = await async_db_connect() return self.conn async def __aexit__(self, exc_type, exc, tb): await self.conn.close() async def main(): async with AsyncDBConnection() as conn: await conn.query('SELECT 1')

异步上下文允许在技术延迟中不阻塞事件循环,提高并发程序的性能。

设问。

可以在async def中使用普通的with吗?

答案: 是的,但是如果上下文管理器内部的操作使用了awaitable(需要await),则需要使用async with。普通的with不支持异步的enter/exit,会阻塞事件循环,或者如果在enter/exit中调用await会导致失败。

示例:

async def foo(): with open('file.txt') as f: # 这是可以的,同步读取 data = f.read() # 但不能在普通上下文中使用await,只能在async with中

由于对主题细节缺乏了解而导致的真实错误示例。


故事

项目: 带有异步API的Web服务。

问题: 数据库连接管理器使用了普通的with,但内部调用了await。这导致了RuntimeError("Cannot use 'await' outside async function")错误,并在生产环境中阻塞了事件循环。


故事

项目: Websockets聊天。

问题: 在处理连接时未关闭websocket资源(使用了普通的同步管理器),这导致了内存泄漏和连接挂起。


故事

项目: 多线程异步任务队列。

问题: 任务管理器未正确实现__aexit__,忘记返回awaitable。因此,任务的完成不是保证的,部分任务在系统中“挂起”。