防止 asyncpg 处理 postgres 的输出? (返回原始数据)

问题描述 投票:0回答:1

我试图从使用 asyncpg 执行的 postgresql 查询返回原始数据(如字符串/字节),而无需 asyncpg 将输出数据解析为记录/字典。就我而言,我使用光标,但我认为这个问题很普遍。

为什么?

我正在返回预处理的 json 数据,为端点做好准备。我不想解析这些数据,将其转换为字典,然后在 python 中将其重新编码为 json。看来很多努力都白费了。我返回的数据非常多,因此我希望防止这种情况会导致性能显着提高。

我的代码基本上是这样的:

query = "SELECT ARRAY_AGG(JSON_STRIP_NULLS('my', 'data', 'from', (select array_agg(somewhere) from databasetable)))"
# Never mind the actual query. It is big, but returns many lines of json.
# eg:
# {"my": "data", "from": [1,2,3]}
# {"my": "data", "from": [1,2,4]}
# {"my": "data", "from": [1,2,5]}

async def my_generator():
  async with get_transaction_somehow() as conn: # type: asyncpg.Connection | asyncpg.pool.PoolConnectionProxy
    async for record in conn.cursor(query, my_data):
      yield record # Here I just want to spew out whatever asyncpg gets from postgres

python postgresql asyncpg
1个回答
0
投票

最简单、最通用的解决方案是在查询中将值强制转换为

text
,这样驱动程序就不会尝试反序列化它。

SELECT some_json_value::text FROM tbl

在 asyncpg 的特定情况下,只有设置了解码器,JSON 值才会被反序列化,因此默认情况下 JSON 值将加载为

str
,但是这样的配置可能不方便,因为通常会自动(反)序列化至少在某些时候需要。

这是一个完整的演示脚本:

import asyncio
import json

import asyncpg


async def main():
    conn = await asyncpg.connect('postgresql:///test')
    await conn.set_type_codec(
        'jsonb', encoder=json.dumps, decoder=json.loads, schema='pg_catalog'
    )
    await conn.execute("""DROP TABLE IF EXISTS t78449946""")
    await conn.execute(
        """
        CREATE TABLE t78449946 (
            c JSONB
        )
    """
    )

    # Insert a record into the created table.
    await conn.execute(
        """INSERT INTO t78449946 (c) VALUES($1)""",
        {},
    )

    row = await conn.fetchrow("""SELECT c FROM t78449946""")
    assert isinstance(row['c'], dict)

    row = await conn.fetchrow("""SELECT c::text FROM t78449946""")
    assert isinstance(row['c'], str)
    await conn.close()


asyncio.get_event_loop().run_until_complete(main())
© www.soinside.com 2019 - 2024. All rights reserved.