使用asyncpg经常执行的操作摘要


psycopg2常用操作的总结-Qiita成为广受欢迎的文章,逐渐增加了LGTM,但是最近asyncpg与aiohttp Server结合使用变得更加流行,因此我也将对此进行总结。

但是,官方文档通常很容易理解,而且容量也不大,因此可以快速阅读所有文档。
asyncpg — asyncpg文档

asyncpg概述

  • 从Python访问PostgreSQL的模块
  • 由于执行了使用asyncio的异步处理,因此只有Python 3.5或更高版本才能使用
  • 它不符合DB-API规范(因为DB-API中指定的规范首先是同步API)

基本用法

安装

1
$ pip install asyncpg

连接

1
2
3
4
5
6
7
8
import asyncpg

dsn = "postgresql://username:password@hostname:5432/database"
conn = await asyncpg.connect(dsn)

# ...

await conn.close()

conn作为asyncpg.connection.Connection对象获得。

创建连接池

1
2
3
4
5
import asyncpg

dsn = "postgresql://username:password@hostname:5432/database"
async with asyncpg.create_pool(dsn) as pool:
    await pool.execute("...")

pool作为asyncpg.pool.Pool对象获得。

您可以从

池中检索连接并使用它,但是也可以直接在该池上执行诸如execute之类的方法。

执行查询

asyncpg允许您直接使用conn.execute查询而不创建游标。

1
await conn.execute("INSERT INTO users(name) VALUES($1)", "foo")

如果在查询中写入$数字并在执行查询时在第二个参数之后指定值,则可以将值嵌入查询中。可以按原样指定某些类型的对象,例如datetime,但是它们在内部进行转换并嵌入到查询中。官方文档描述了要转换的类型以及转换方式,您可以自己定制它们。

获取数据

您可以通过使用诸如fetch而不是

execute之类的方法执行查询来获得结果。

1
await conn.fetch("SELECT * FROM users")  #=> [<Record id='1' name='foo'>, <Record id='2' name='bar'>]

结果作为asyncpg.Record对象的列表获得。

使用fetchrow仅获取第一行和fetchval仅获取第一行和列的值也很方便。

1
await conn.fetchrow("SELECT * FROM users WHERE id = $1", "1")  #=> <Record id='1' name='foo'>
1
await conn.fetchval("SELECT COUNT(1) FROM users")  #=> 2

关于记录对象

Record对象的行为类似于元组或dict,因此您无需费心将其转换为另一种数据类型。

1
2
3
4
record = await conn.fetchrow("SELECT * FROM users WHERE id = $1", "1")

record[1]  #=> インデックスでアクセス
record["name"]  #=> キーでアクセス

使用交易

使用事务时,将过程写入异步上下文管理器(与之异步)块中。

1
2
async with connection.transaction():
    await conn.execute("...")

如果使用

异步方式启动事务,则该事务将在块结束时自动提交,因此您无需显式提交。

设置超时

您可以通过在创建连接时指定command_timeout的秒数来设置查询的默认超时。

1
conn = await asyncpg.connect(dsn, command_timeout=60)

要为每个

查询执行分别设置超时,请在executefetch的参数中指定timeout

1
await conn.execute("...", timeout=60)

有用的技巧

将获取的数据转换为Pandas DataFrame

的获取结果是Record对象的列表,因此您可以将其放在pd.DataFrame()中。

1
2
3
4
5
6
7
import pandas as pd

records = await conn.fetch("SELECT * FROM users")
if len(records) > 0:
    df = pd.DataFrame(records, columns=list(records[0].keys()))
else:
    # 結果が0件だった場合の処理

插入Pandas DataFrame

的内容

asyncpg有很多COPY方法,并且您可以使用copy_records_to_table轻松插入INSERT Pandas DataFrame,它使用COPY命令批量插入一个元组列表。

1
await conn.copy_records_to_table("users", records=df.itertuples(), columns=df.columns)

插入CSV文件

同样,如果使用copy_to_table,则可以轻松地从CSV格式的文件中插入。

1
await conn.copy_to_table("users", source="users.csv", format="csv")

许多指定的选项直接流向COPY查询,因此,如果您了解COPY查询的规范,则可以使用它们。 (格式,空值,标题等)
PostgreSQL:文档:COPY