You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确返回SQLAlchemy异步会话?现有实现优化疑问

问题分析与优化方案

报错原因

你编写的get_session方法因使用yield关键字,成为了异步生成器。异步生成器属于可迭代对象,不能通过await直接获取返回值,必须使用async for循环遍历或调用anext()方法,直接await会触发TypeError: object async_generator can't be used in 'await' expression。

优化方案

方案一:异步上下文管理器(推荐)

使用contextlib.asynccontextmanager装饰器将get_session改造为异步上下文管理器,既简化调用,又能自动管理会话的生命周期:

from contextlib import asynccontextmanager

class Database(AbstractDatabase):
    def __init__(self):
        self._engine = AsyncEngine(create_engine("postgresql+asyncpg://postgres:postgres@localhost/test", echo=True, future=True))
        self._session_maker = sessionmaker(self._engine, class_=AsyncSession, expire_on_commit=False)

    @asynccontextmanager
    async def get_session(self):
        async with self._session_maker() as session:
            yield session

# UsersRepository 调用示例
class UsersRepository(AbstractUsersRepository):
    def __init__(self, db: AbstractDatabase):
        self._db = db

    async def get(self, entity_id: UUID) -> User:
        async with self._db.get_session() as session:
            return await session.get(User, entity_id)

方案二:简化会话生成器调用

给Database类添加一个快捷方法,直接返回会话实例的上下文,减少冗余的括号调用:

class Database(AbstractDatabase):
    def __init__(self):
        self._engine = AsyncEngine(create_engine("postgresql+asyncpg://postgres:postgres@localhost/test", echo=True, future=True))
        self._session_maker = sessionmaker(self._engine, class_=AsyncSession, expire_on_commit=False)

    def session(self):
        return self._session_maker()

# UsersRepository 调用示例
class UsersRepository(AbstractUsersRepository):
    def __init__(self, db: AbstractDatabase):
        self._db = db

    async def get(self, entity_id: UUID) -> User:
        async with self._db.session() as session:
            return await session.get(User, entity_id)

方案三:让Database类本身成为异步上下文管理器

适合短生命周期的数据库实例场景,直接通过async with获取会话:

class Database(AbstractDatabase):
    def __init__(self):
        self._engine = AsyncEngine(create_engine("postgresql+asyncpg://postgres:postgres@localhost/test", echo=True, future=True))
        self._session_maker = sessionmaker(self._engine, class_=AsyncSession, expire_on_commit=False)
        self._session = None

    async def __aenter__(self):
        self._session = self._session_maker()
        await self._session.__aenter__()
        return self._session

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self._session.__aexit__(exc_type, exc_val, exc_tb)

# 调用示例
async def fetch_user(user_id: UUID):
    async with Database() as session:
        return await session.get(User, user_id)

内容的提问来源于stack exchange,提问作者sln

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:02:51