asyncpg传入int参数触发DataError:期望str却得到int,原因是什么?
asyncpg传入整数参数报错的原因及解决办法
问题描述
我承认不太理解asyncpg的编解码器工作机制,但其表现似乎与我的预期相悖:
import asyncio import asyncpg async def main(): conn = await asyncpg.connect('postgresql://postgres@localhost/test') print(await conn.fetchval("select $1", 'a')) # 正常运行:输出'a' print(await conn.fetchval("select $1", 1)) # 报错:invalid input for query argument $1: 1 (expected str, got int) asyncio.run(main())
看起来asyncpg要求参数必须是字符串,但我想传入整数,为何会执行失败?
原因分析
这个报错并非因为asyncpg只接受字符串参数,核心原因是你大概率给当前连接注册了自定义的字符串编解码器,覆盖了默认的基础类型处理逻辑。
默认状态下,asyncpg会自动适配整数、字符串等PostgreSQL基础类型的编码/解码,不会出现这类类型不匹配的报错。如果出现这个问题,你可以检查代码中是否有类似如下的自定义编解码器注册操作:
await conn.set_type_codec( 'text', encoder=str, decoder=str, schema='pg_catalog' )
当你注册了针对pg_catalog.text类型的自定义编解码器后,PostgreSQL执行select $1时会默认将参数推断为text类型,此时asyncpg会按照你指定的编解码器要求参数必须是字符串类型,传入整数就会触发类型检查报错。
解决办法
- 恢复默认编解码器:如果不需要自定义的文本类型编解码逻辑,直接移除
set_type_codec相关的调用,asyncpg就会回到默认的类型处理模式,自动识别并处理整数参数。 - 显式指定参数类型:如果必须保留自定义编解码器,在查询时显式声明参数的PostgreSQL类型,让asyncpg使用对应类型的编解码器处理:
print(await conn.fetchval("select $1::int", 1)) - 针对自定义类型注册编解码器:避免覆盖
pg_catalog下的系统默认类型编解码器,只针对你自己定义的数据库类型注册编解码逻辑。
内容的提问来源于stack exchange,提问作者DMac the Destroyer
相关产品推荐
相关产品推荐

