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

如何在Python中结合aiomysql.create_pool与SQLAlchemy?遇类型错误

问题解决:aiomysql cursor执行SQLAlchemy Select对象报错

错误原因

aiomysql的普通游标(通过conn.cursor()获取)仅支持执行原生SQL字符串,而你传入的user.select()是SQLAlchemy构建的Select查询对象,游标内部尝试计算该对象长度时,因为它不是字符串类型,所以抛出TypeError: object of type 'Select' has no len()。

解决方法

方法一:使用aiomysql的SQLAlchemy集成(推荐)

这是最适配SQLAlchemy的方式,直接用你注释掉的aiomysql.sa.create_engine来创建引擎,它会自动处理SQLAlchemy查询对象到原生SQL的转换:

修改上下文管理代码

async def pg_context(app):
    conf = app['config']['mysql']
    # 恢复使用aiomysql.sa的create_engine
    engine = await aiomysql.sa.create_engine(
        db=conf['database'],
        user=conf['username'],
        password=conf['password'],
        host=conf['host'],
        port=conf['port'],
    )
    app['db'] = engine

    yield

    app['db'].close()
    await app['db'].wait_closed()

修改请求处理代码

sa引擎的连接支持直接执行SQLAlchemy查询对象,无需手动转换:

async def index(request):
    async with request.app['db'].acquire() as conn:
        # 直接执行Select对象,返回结果集
        result = await conn.execute(user.select())
        # 提取所有记录为字典列表
        questions = [dict(row) for row in result]
        return web.Response(text=str(questions))

方法二:手动转换Select对象为原生SQL(适合坚持用create_pool的场景)

如果必须使用普通的create_pool,需要将SQLAlchemy的Select对象编译为原生SQL字符串,并提取参数——绝对不要直接用str()拼接参数,避免SQL注入风险:

async def index(request):
    async with request.app['db'].acquire() as conn:
        cursor = await conn.cursor()
        # 编译Select对象,生成带占位符的SQL和对应参数
        select_stmt = user.select()
        compiled = select_stmt.compile(
            compile_kwargs={"literal_binds": False},
            dialect=conn.dialect
        )
        # 执行带参数的SQL
        await cursor.execute(str(compiled), compiled.params)
        records = await cursor.fetchall()
        # 将记录转为字典(通过cursor.description获取字段名)
        columns = [desc[0] for desc in cursor.description]
        questions = [dict(zip(columns, row)) for row in records]
        return web.Response(text=str(questions))

注意:compile_kwargs={"literal_binds": False}会保留安全的占位符(如%s),配合compiled.params传入参数,这是生产环境的标准做法。若设置为True会直接把参数拼入SQL,仅用于调试,禁止在生产环境使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:03:14