asyncpg – асинхронный клиент PostgreSQL

онлайн тренер по питону
Онлайн-тренажер Python 3 для начинающих

Теория без воды. Задачи с автоматической проверкой. Подсказки на русском языке. Работает в любом современном браузере.

начать бесплатно

Введение

С ростом популярности асинхронных веб-фреймворков, таких как FastAPI и Starlette, возрастает потребность в быстрых, неблокирующих способах взаимодействия с базой данных. asyncpg — это асинхронный клиент для PostgreSQL, разработанный с нуля для максимальной производительности.

asyncpg – асинхронный клиент PostgreSQL предлагает низкоуровневый, быстрый и эффективный способ работы с PostgreSQL в async/await стиле, что делает его отличным выбором для современных Python-приложений.

Установка и подключение

Установка библиотеки:

bash
pip install asyncpg

Подключение к базе:

python
import asyncpg import asyncio async def main(): conn = await asyncpg.connect(user='postgres', password='secret', database='test_db', host='127.0.0.1') await conn.close() asyncio.run(main())

Асинхронность в Python и роль asyncpg

asyncpg использует async/await и совместим с asyncio, что позволяет выполнять неблокирующие запросы к PostgreSQL, не блокируя event loop. Это критически важно для высоконагруженных приложений и API.

Отличие от psycopg2: последний является синхронным, и его использование в асинхронных приложениях может вызывать "зависания".

Основные функции и методы

python
conn = await asyncpg.connect(...) await conn.execute("CREATE TABLE IF NOT EXISTS users(id serial PRIMARY KEY, name text)") await conn.execute("INSERT INTO users(name) VALUES($1)", "Иван") rows = await conn.fetch("SELECT * FROM users") row = await conn.fetchrow("SELECT * FROM users WHERE id=$1", 1) await conn.close()
  • execute() — выполнение SQL без возврата данных

  • fetch() — получение всех строк

  • fetchrow() — одна строка

  • fetchval() — одно значение

Работа с транзакциями

python
async with conn.transaction(): await conn.execute("UPDATE users SET name=$1 WHERE id=$2", "Анна", 1)

Можно также использовать ручное управление транзакциями:

python
tr = conn.transaction() await tr.start() try: ... await tr.commit() except: await tr.rollback()

Пул соединений в asyncpg

Пул позволяет эффективно переиспользовать соединения:

python
pool = await asyncpg.create_pool(user='postgres', password='secret', database='test_db', host='127.0.0.1') async with pool.acquire() as conn: await conn.fetch(...)

Полезно для FastAPI, где каждое подключение может обрабатывать множество запросов.

Поддержка типов данных PostgreSQL

  • Поддерживаются JSON, UUID, массивы, даты

  • Можно использовать Python-объекты напрямую

  • Кастомные преобразования через set_type_codec

python
await conn.set_type_codec('json', encoder=json.dumps, decoder=json.loads, schema='pg_catalog')

Работа с параметризированными запросами

python
await conn.execute("INSERT INTO users(name) VALUES($1)", "Пётр")

Плейсхолдеры в asyncpg обозначаются как $1, $2 и т.д.

Производительность и масштабируемость

  • asyncpg быстрее, чем psycopg2 и aiopg

  • Лёгкий, без ORM-абстракций

  • Подходит для систем с большим количеством одновременных запросов

Интеграция с FastAPI, Starlette и другими

python
from fastapi import FastAPI, Depends app = FastAPI() pool = None @app.on_event("startup") async def startup(): global pool pool = await asyncpg.create_pool(...) @app.get("/users") async def get_users(): async with pool.acquire() as conn: return await conn.fetch("SELECT * FROM users")

Сравнение с другими драйверами PostgreSQL

Драйвер Асинхронность Скорость Совместимость Подходит для
asyncpg Да Очень высокая PostgreSQL FastAPI, Starlette
psycopg2 Нет Средняя PostgreSQL Синхронные приложения
aiopg Да Средняя PostgreSQL Async, но медленнее
SQLAlchemy Опционально Средняя Разные СУБД ORM-приложения

Интеграция с ORMs

Хотя asyncpg не является ORM, он может использоваться в сочетании с:

  • Gino (ORM поверх asyncpg)

  • Tortoise ORM

  • SQLAlchemy 2.0 async (через asyncpg как backend)

Тестирование и отладка

  • Используйте временную базу

  • Очищайте таблицы перед/после тестов

  • Логируйте SQL-запросы вручную, так как логгера встроенного нет

Часто задаваемые вопросы (FAQ)

1. Что такое asyncpg?
Асинхронный PostgreSQL-драйвер для Python, построенный на asyncio.

2. Зачем использовать asyncpg вместо psycopg2?
Для асинхронных приложений — это быстрее и не блокирует event loop.

3. Поддерживает ли asyncpg пул соединений?
Да, через create_pool().

4. Безопасны ли запросы в asyncpg?
Да, при использовании параметров $1, $2 и т.д.

5. Можно ли использовать asyncpg с SQLAlchemy?
Непосредственно — нет, но можно использовать как backend с SQLAlchemy async.

6. Подходит ли asyncpg для продакшн-проектов?
Да, активно используется и стабильно работает.

Полный справочник по работе с библиотекой asyncpg для Python

Установка

bash
pip install asyncpg

Подключение к базе данных

python
import asyncpg import asyncio async def main(): conn = await asyncpg.connect( user='postgres', password='password', database='testdb', host='localhost' ) await conn.close() asyncio.run(main())

Использование пула соединений (рекомендуется)

python
pool = await asyncpg.create_pool( user='postgres', password='password', database='testdb', host='localhost', min_size=1, max_size=10 ) async with pool.acquire() as conn: await conn.execute('SELECT 1')

Выполнение SQL-запросов

execute(): команды без возврата данных

python
await conn.execute("INSERT INTO users (name, age) VALUES ($1, $2)", "Alice", 30)

fetch(): получить все строки

python
rows = await conn.fetch("SELECT * FROM users WHERE age > $1", 20) for row in rows: print(row["name"], row["age"])

fetchrow(): первая строка результата

python
row = await conn.fetchrow("SELECT * FROM users WHERE name = $1", "Alice")

fetchval(): одно значение

python
age = await conn.fetchval("SELECT age FROM users WHERE name = $1", "Alice")

Плейсхолдеры: $1, $2, ...

python
await conn.execute("UPDATE users SET age = $1 WHERE name = $2", 31, "Alice")

Создание таблиц

python
await conn.execute(""" CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name TEXT, age INT ) """)

Работа с транзакциями

python
async with conn.transaction(): await conn.execute("INSERT INTO users (name, age) VALUES ($1, $2)", "Bob", 25) await conn.execute("UPDATE users SET age = age + 1 WHERE name = $1", "Bob")

Преобразование типов

asyncpg возвращает строки как Record (подобие словаря и кортежа).

python
row = await conn.fetchrow("SELECT * FROM users") print(row["name"]) # доступ по имени print(row[0]) # доступ по индексу

Работа с JSON

python
await conn.execute("INSERT INTO logs (data) VALUES ($1)", {"event": "login"})

asyncpg автоматически сериализует/десериализует JSON-данные.


Конвертация в словари

python
dicts = [dict(row) for row in await conn.fetch("SELECT * FROM users")]

Пример с FastAPI

python
from fastapi import FastAPI import asyncpg app = FastAPI() db_pool = None @app.on_event("startup") async def startup(): global db_pool db_pool = await asyncpg.create_pool(database="testdb", user="postgres", password="password") @app.get("/users") async def get_users(): async with db_pool.acquire() as conn: rows = await conn.fetch("SELECT * FROM users") return [dict(row) for row in rows]

Использование SQL-файлов

python
with open("query.sql") as f: query = f.read() await conn.execute(query, param1, param2)

Поддержка параметров соединения

python
await asyncpg.connect( dsn="postgresql://postgres:password@localhost:5432/testdb", timeout=10.0, command_timeout=5.0 )

Почему выбирать asyncpg

Причина Объяснение
Высокая производительность Быстрее psycopg2 и других аналогов.
Полная асинхронность Совместимость с asyncio и асинхронными фреймворками.
Поддержка всех типов PostgreSQL Включая JSON, UUID, массивы и т.д.
Простая интеграция Идеально подходит для FastAPI, Starlette, Quart.

Заключение

asyncpg – асинхронный клиент PostgreSQL — это выбор №1 для высоконагруженных асинхронных Python-приложений, использующих PostgreSQL. Он сочетает производительность, простоту и богатую поддержку типов данных, позволяя быстро строить масштабируемые API и сервисы.