El controlador de PostgreSQL para Python es psycopg. La versión 3 es la actual y, con la variante binary, se instala sin compilar nada. Lo que la versión anterior de esta página explicaba con psycopg2 sigue valiendo, pero hoy hay una forma más sencilla.
También te puede interesar
Instalarlo
pip install "psycopg[binary]"
Dentro de un entorno virtual. Con [binary] viene ya compilado, con su propia copia de la biblioteca de PostgreSQL, y no hace falta el sudo apt-get install gcc libpq-dev python3-dev que necesitaba psycopg2. Las comillas alrededor evitan que algunas terminales interpreten los corchetes.
import psycopg2, es la versión anterior. Sigue funcionando y se sigue manteniendo, pero para un proyecto nuevo conviene psycopg 3: se importa como psycopg, sin número.Conectar, crear e insertar
import psycopg
with psycopg.connect("host=localhost dbname=pruebas user=app password=clave") as con:
print("conectado a", con.execute("SELECT version()").fetchone()[0].split(" on ")[0])
con.execute("""
CREATE TABLE usuarios (
id SERIAL PRIMARY KEY,
correo TEXT NOT NULL UNIQUE,
nombre TEXT
)""")
with con.cursor() as cur:
cur.executemany("INSERT INTO usuarios (correo, nombre) VALUES (%s, %s)",
[("ana@ejemplo.com", "Ana Pérez"), ("luis@ejemplo.com", "Luis Gómez")])
nuevo = cur.execute("INSERT INTO usuarios (correo, nombre) VALUES (%s, %s) RETURNING id",
("eva@ejemplo.com", "Eva Ruiz")).fetchone()[0]
print("id de la última:", nuevo)
for fila in cur.execute("SELECT id, correo, nombre FROM usuarios ORDER BY id"):
print(" ", fila)salidaconectado a PostgreSQL 18.6 (Debian 18.6-1.pgdg13+2) id de la última: 3 (1, 'ana@ejemplo.com', 'Ana Pérez') (2, 'luis@ejemplo.com', 'Luis Gómez') (3, 'eva@ejemplo.com', 'Eva Ruiz')
Tres cosas propias de psycopg 3. con.execute existe directamente en la conexión, sin crear un cursor, para las consultas sueltas. RETURNING id es de PostgreSQL y devuelve el id recién creado en la misma consulta. Y el with de la conexión hace commit al salir si todo fue bien, o deshace los cambios si saltó una excepción.
abriendo otra conexión despuésfilas tras el with: 3
Varias operaciones, todo o nada
try:
with con.transaction():
con.execute("INSERT INTO usuarios (correo) VALUES (%s)", ("zoe@ejemplo.com",))
con.execute("INSERT INTO usuarios (correo) VALUES (%s)", ("ana@ejemplo.com",))
except psycopg.errors.UniqueViolation as e:
print("UniqueViolation:", str(e).splitlines()[0])
print("¿entró zoe?", con.execute("SELECT count(*) FROM usuarios WHERE correo = %s",
("zoe@ejemplo.com",)).fetchone()[0])salidaUniqueViolation: duplicate key value violates unique constraint "usuarios_correo_key" ¿entró zoe? 0
La segunda inserción falla porque Ana ya existe, y como estaban dentro de la misma transacción, la primera también se deshace: Zoe no entra. Es lo que quieres cuando dos cambios tienen sentido solo juntos, como cobrar y anotar el pedido.
Filas como diccionarios
from psycopg.rows import dict_row
with con.cursor(row_factory=dict_row) as cur:
print(cur.execute("SELECT correo, nombre FROM usuarios WHERE id = %s", (1,)).fetchone())salida{'correo': 'ana@ejemplo.com', 'nombre': 'Ana Pérez'}Más legible que acordarse de que el nombre es la columna 2.
%s, pero no es formato de cadenas. Nunca escribas "... WHERE id = %s" % valor ni una f-string: eso pega el valor dentro del SQL y abre la puerta a una inyección. Pasa siempre los valores aparte, como segundo argumento de execute; en la página de MariaDB está la demostración de lo que pasa si no.Más información en inglés: Connect to PostgreSQL database in Python.
Todo el código se ejecutó con Python 3.14 en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.