Короткий ответ
psycopg2 — синхронный драйвер, каждый вызов блокирует текущий поток/процесс до получения ответа от БД, а asyncpg — асинхронный драйвер, работающий через event loop asyncio и позволяющий не блокировать поток на время ожидания ответа от сети/БД.
Как это работает подробнее
psycopg2 выполняет сетевой I/O синхронно, поэтому внутри асинхронного приложения (например, FastAPI с async def) вызов psycopg2 заблокирует весь event loop, если не выполнить его в отдельном потоке. asyncpg встраивается в event loop через await, уступая управление другим задачам на время ожидания сети.
Пример кода
example.py
import asyncio
import asyncpg
async def get_user(email: str):
conn = await asyncpg.connect("postgresql://user:pass@localhost/db")
try:
row = await conn.fetchrow("SELECT id, name FROM users WHERE email = $1", email)
return dict(row) if row else None
finally:
await conn.close()
# asyncio.run(get_user("alice@example.com")) — вызов не блокирует другие корутины на время ожидания БДЧто использовать на практике
- Практика. Для асинхронных фреймворков (FastAPI, aiohttp) выбирают asyncpg или async-обёртки SQLAlchemy/Django ORM; для классических WSGI-приложений (Flask, обычный Django) psycopg2 остаётся стандартным выбором.
Подводные камни
- Ошибка. Вызывают синхронный psycopg2 напрямую внутри async def обработчика без выноса в threadpool, убирая выигрыш от асинхронности — один медленный запрос блокирует event loop для всех остальных.