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

SQLAlchemy中位置(无命名)参数的使用方法及报错排查

SQLAlchemy使用位置(无命名)参数的正确方案

报错根因

你碰到的AttributeError: 'list' object has no attribute 'keys'错误,根本原因是SQLAlchemy从1.4版本开始重构了参数校验逻辑:用text()包裹的原生SQL,默认会把第二位置传入的参数识别为「键值对格式的参数字典」。你直接把数字1当参数传进去,底层代码想从这个参数里读字典键名,自然就报错了。

具体实现方式

  • SQLAlchemy 2.0+ 原生位置占位支持
    新版本专门为习惯无命名传参的用户开放了适配开关,只要在构造text()语句时加上positional=True参数,就可以直接在SQL里用?做占位符,按原生逻辑传位置参数:
    import sqlalchemy
    from sqlalchemy import text
    
    engine = sqlalchemy.create_engine('mysql://py:123@localhost/py', echo=True)
    con = engine.connect()
    # 开启positional模式后,直接用?占位,按顺序传参即可
    res = con.execute(
        text("select uid, name from users where uid = ?", positional=True),
        1
    )
    
  • 低版本(1.4及更早)兼容方案
    旧版本没有专门的位置参数开关,想用无命名的效果,最省心的方式是直接用纯数字当占位符名——完全不需要给每个参数起有意义的变量名,只要占位符的数字顺序和你传值的顺序对应,写出来的SQL和原生位置参数没有任何区别:
    # 用纯数字作为占位符标识,按位置传对应的值
    res = con.execute(
        text("select uid, name from users where uid = :0"),
        {"0": 1}
    )
    # 多个参数时直接按顺序填数字占位即可
    res = con.execute(
        text("select uid, name from users where uid = :0 and name = :1"),
        {"0": 1, "1": "test"}
    )
    
  • 追求完全原生无ORM层绑定的写法时,可以直接从引擎拿原生DBAPI连接,这层完全兼容原生位置传参逻辑,不受SQLAlchemy参数校验规则限制:
raw_con = engine.raw_connection()
cursor = raw_con.cursor()
# 原生连接直接支持?占位的位置传参
cursor.execute("select uid, name from users where uid = ?", (1,))

注意:所有参数传递不要省略元组/列表包裹,哪怕只有一个参数,原生DBAPI规范里位置参数都需要按可迭代格式传入,避免触发类型校验错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 14:54:02