psycopg (v3)
psycopg v3 — the successor to psycopg2. Completely rewritten. Install is 'psycopg' (no number), import is 'import psycopg'. Supports both sync and native async (AsyncConnection). Current version: 3.3.3 (Mar 2026). NOT backward compatible with psycopg2 — several behavior changes. For new projects use psycopg over psycopg2. Django 4.2+ supports psycopg v3.
Common errors
-
OperationalError: could not connect to server
cause This error often indicates issues with database connection parameters (host, port, user, password, dbname), network connectivity, or the PostgreSQL server not running or being inaccessible.fixVerify that your database credentials and connection string are correct, the PostgreSQL server is running and reachable, and that no firewall is blocking the connection. Example fix: `conn = psycopg.connect(host='localhost', port=5432, dbname='your_db', user='your_user', password='your_password')`. -
OperationalError: fe_sendauth: no password supplied
cause This error occurs when the PostgreSQL server requires password authentication for the user, but `psycopg` is not provided with a password in the connection string or through a `.pgpass` file.fixProvide the correct password in the connection string. Example fix: `conn = psycopg.connect(dbname='your_db', user='your_user', password='your_password', host='localhost')`. Alternatively, ensure your `pg_hba.conf` allows passwordless connections for the specified user and host, or configure a `.pgpass` file. -
ModuleNotFoundError: No module named 'psycopg2'
cause This error happens when you have installed `psycopg` (version 3) but your code attempts to import the older `psycopg2` library, which is a different package. `psycopg` is not backward compatible with `psycopg2` imports.fixIf you intend to use `psycopg` (version 3), change your import statements from `import psycopg2` to `import psycopg`. If you genuinely need `psycopg2`, install it separately using `pip install psycopg2-binary`. -
AttributeError: 'Connection' object has no attribute 'mogrify'
cause In `psycopg` (version 3), the `mogrify` method was moved from the `Connection` object to the `Cursor` object, unlike `psycopg2` where it was available on both.fixAccess `mogrify` through a cursor object. Example fix: `conn = psycopg.connect(...); cur = conn.cursor(); query = cur.mogrify('INSERT INTO test VALUES (%s)', ('value',));` -
psycopg.InterfaceError: Psycopg cannot use the 'ProactorEventLoop' to run in async mode. Please use a compatible event loop, for instance by setting 'asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())'.
cause This error occurs when using `psycopg`'s asynchronous features on Windows with the default `ProactorEventLoop`, which is not compatible. `psycopg` requires a different event loop policy for async operations on this platform.fixBefore running any async code, set the event loop policy to `WindowsSelectorEventLoopPolicy`. Example fix: `import asyncio; import sys; if sys.platform == 'win32': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()); asyncio.run(your_async_function())`.
Warnings
- breaking 'with connection' behavior changed from psycopg2. In psycopg2 it manages the transaction. In psycopg v3 it closes the connection. Major silent bug when migrating.
- breaking cursor_factory moved from cursor() to connect(). psycopg2 pattern: conn.cursor(cursor_factory=DictCursor). psycopg v3: psycopg.connect(..., row_factory=dict_row).
- breaking Package name changed. Install: 'psycopg' not 'psycopg3' or 'psycopg2'. Import: 'import psycopg' not 'import psycopg2'. LLMs confuse the package names.
- gotcha psycopg2 and psycopg cannot be used interchangeably in the same codebase — APIs differ. Cannot drop-in replace 'import psycopg2' with 'import psycopg'.
- gotcha row_factory=dict_row is imported from psycopg.rows, not from psycopg directly. 'from psycopg import dict_row' fails.
- gotcha COPY command API changed. psycopg2 had copy_expert(), copy_from(), copy_to(). psycopg v3 has a single copy() method with unified interface.
- breaking psycopg.OperationalError: connection failed: Connection refused indicates the PostgreSQL server is not running, is not listening on the specified host/port, or is inaccessible (e.g., due to firewall rules). This is an infrastructure issue, not a psycopg library usage error.
- breaking Connection refused: psycopg.OperationalError when connecting to PostgreSQL. This error indicates that the database server is not running, is not accessible at the specified host/port, or is not configured to accept incoming connections from the client.
Install
-
pip install psycopg -
pip install psycopg[binary] -
pip install psycopg[pool]
Imports
- connect (sync)
import psycopg conn = psycopg.connect('...') # WRONG: 'with conn' closes the connection in v3 # In psycopg2, 'with conn' only managed the transaction with conn: pass # connection is now closed!import psycopg # row_factory for dict rows — moved to connect() not cursor() with psycopg.connect( 'postgresql://user:pass@localhost/mydb', row_factory=psycopg.rows.dict_row ) as conn: with conn.cursor() as cur: cur.execute('SELECT * FROM users WHERE id = %s', (user_id,)) row = cur.fetchone() print(row['name']) - AsyncConnection
# Using psycopg2 in async context — blocks event loop import psycopg2 async def main(): conn = psycopg2.connect(...) # blocksimport psycopg import asyncio async def main(): async with await psycopg.AsyncConnection.connect( 'postgresql://user:pass@localhost/mydb', row_factory=psycopg.rows.dict_row ) as conn: async with conn.cursor() as cur: await cur.execute('SELECT * FROM users') rows = await cur.fetchall() for row in rows: print(row['name']) asyncio.run(main())
Quickstart
# pip install psycopg
import psycopg
from psycopg.rows import dict_row
# Sync usage
with psycopg.connect(
'postgresql://user:pass@localhost/mydb',
row_factory=dict_row
) as conn:
with conn.cursor() as cur:
cur.execute(
'SELECT id, name FROM users WHERE active = %s',
(True,)
)
for row in cur.fetchall():
print(row['name']) # dict access
conn.commit()