Cómo acceder a un servidor de base de datos PostgreSQL mediante el lenguaje de programación Python y el módulo psycopg2. Eliminamos una tabla existente (drop table), creamos una tabla (create table), hacemos una inserción de registros (insert), hacemos una selección (select), eliminamos un registro (delete) y actualizamos un registro (update).

Requisitos de acceso a PostgreSQL mediante Python

Necesitaremos disponer de un equipo con el motor de base de datos PostgreSQL. En el siguiente enlace explicamos cómo desplegar un contenedor docker con PostgreSQL y con acceso remoto:

En este otro tutorial instalamos PostgreSQL en Windows:

Para el desarrollo de la aplicación Python usaremos el IDE Visual Studio Code. En el siguiente enlace explicamos cómo preparar Visual Studio Code para desarrollar en Python:

Necesitaremos instalar el paquete psycopg2, que nos proporcionará acceso nativo a PostgreSQL. Para instalarlo, desde la línea de comandos, ejecutaremos:

pip install psycopg2

Fichero INI con los datos de conexión a PostgreSQL y lectura en Python de este fichero

En este caso, para la conexión con el servidor de PostgreSQL, usaremos un fichero de configuración INI, con el siguiente contenido de ejemplo:

[postgresql]
servidor=localhost
puerto=5432
base_datos=bdproyectoa
usuario=usuproyectoa
contrasena=la_contraseña

Estableceremos, como se ve en el ejemplo, en la clave «postgresql», las siguientes subclaves y sus valores:

  • servidor: IP o nombre de red del servidor que contiene PostgreSQL.
  • puerto: puerto de conexión con el servidor PostgreSQL. Por defecto 5432.
  • base_datos: nombre de la base de datos a la que nos conectaremos.
  • usuario: usuario de PostgreSQL con el que nos conectaremos.
  • contrasena: contraseña del usuario anterior.

Guardaremos este fichero en la misma carpeta que los ficheros de la aplicación que crearemos a continuación, por ejemplo con el nombre con.conf.

Crearemos un fichero Python con el nombre configuracion.py y el siguiente código Python. Usaremos la función de este fichero leerINI para leer los valores del fichero INI:

from configparser import ConfigParser
import os.path

# Lee todos los valores de la sección pasada por 
# argumento de un fichero INI
def leerINI(ficheroINI="con.conf", seccion="postgresql"):
    parseador = ConfigParser()
    if os.path.exists(ficheroINI):        
        parseador.read(ficheroINI)

        # Obtenemos los datos de la sección postgresql (por defecto si no se ha especificado otra)
        configINI = {}
        if parseador.has_section(seccion):
            valores = parseador.items(seccion)
            for valor in valores:
                configINI[valor[0]] = valor[1]
        else:
            raise Exception("No se ha encontrado la sección {0} en el fichero INI {1}".format(seccion, ficheroINI))
        return configINI
    else:
        raise Exception("No se ha encontrado el fichero INI {1}".format(ficheroINI))        

"""
if __name__ == "__main__":
    config = leerINI()
    print(configINI)
"""

Guardaremos el contenido anterior en el fichero configuracion.py y en la misma carpeta que el resto de ficheros de la aplicación.

Fichero Python para acceso a base de datos PostgreSQL (drop, create, insert, select, update, delete)

A continuación, mostramos el código fuente en Python del fichero postgresql.py, con las líneas más importantes comentadas. Este fichero es un ejemplo de acceso a un servidor de base de datos PostgreSQL y de ejecución de las habituales sentencias SQL: crear tabla, insertar registros en una tabla, seleccionar registros, eliminar registros, actualizar registros, etc.:

import psycopg2
from configuracion import leerINI
from datetime import datetime as dt

FICHERO_INI = "D:\\Mis documentos\\ProyectoA\\Python\\postgresql\\con.conf"
SECCION_INI_BD = "postgresql"

# Conectar al servidor de base de datos PostgreSQL
# Se le pasa un diccionario con la clave:valor de los datos de conexión
def conectarBDPosgreSQL(configuracion):
    try:
        # Conectamos al servidor de BD PostgreSQL indicando en en fichero INI
        with psycopg2.connect(host=configuracion.get("servidor"),
                              dbname=configuracion.get("base_datos"),
                              user=configuracion.get("usuario"),
                              password=configuracion.get("contrasena"),
                              port=configuracion.get("puerto")) as conexion:
            print("Conectado correctamente al servidor PostgreSQL [{0}:{1}]".format(
                configuracion.get("servidor"), configuracion.get("puerto")))
            return conexion
    except (psycopg2.DatabaseError, Exception) as error:
        print(error)

if __name__ == '__main__':
    # Leemos la configuración de conexión en el fichero INI
    configuracion = leerINI(ficheroINI=FICHERO_INI, seccion=SECCION_INI_BD)
    # Conectamos al servidor con la configuración del fichero INI
    conexion = conectarBDPosgreSQL(configuracion)
    # Activamos autocommit para no tener que hacer un commit en cada sentencia de modificación
    conexion.autocommit = True
    
    # Eliminamos la tabla si existe
    # Atención con este proceso pues puede eliminar una tabla completa existente y todos sus datos
    sqlEliminarTabla = "DROP TABLE IF EXISTS factura"
    
    # Preparamos las consultas SQL que usaremos
    sqlCrearTabla = """
        CREATE TABLE factura
        (
            numero serial PRIMARY KEY,
            codigo_cliente integer,
            importe money,
            fecha date
        );
        """

    dia = dt.now().day
    mes = dt.now().month
    ano = dt.now().year
    sqlInserts = (f"INSERT INTO factura (codigo_cliente, importe, fecha) VALUES (11, 1555.21, to_timestamp('{dia}-{mes}-{ano}', 'dd-mm-yyyy'))",
                  f"INSERT INTO factura (codigo_cliente, importe, fecha) VALUES (10, 100.5,  to_timestamp('{dia}-{mes}-{ano}', 'dd-mm-yyyy'))",
                  f"INSERT INTO factura (codigo_cliente, importe, fecha) VALUES (11, 1000,  to_timestamp('{dia}-{mes}-{ano}', 'dd-mm-yyyy'))",
                  f"INSERT INTO factura (codigo_cliente, importe, fecha) VALUES (20, 10.95,  to_timestamp('{dia}-{mes}-{ano}', 'dd-mm-yyyy'))",
                  f"INSERT INTO factura (codigo_cliente, importe, fecha) VALUES (33, 10.95,  to_timestamp('{dia}-{mes}-{ano}', 'dd-mm-yyyy'))")
        
    sqlSelect = "SELECT * FROM factura ORDER BY fecha DESC"
    
    sqlUpdate = "UPDATE factura SET importe = 5000 WHERE codigo_cliente=20"
    
    sqlDelete = "DELETE FROM factura WHERE codigo_cliente = 33"
    
    # Iniciamos la ejecución de las consultas SQL
    with conexion.cursor() as cursor:
        # Eliminamos la tabla "factura" si ya existe
        # Atención con este proceso pues puede eliminar una tabla completa existente y todos sus datos
        print("Eliminando tabla factura...")
        cursor.execute(sqlEliminarTabla)
        print("Tabla factura eliminada...")
        
        # Creamos una tabla llamada "factura"
        print("Creando tabla factura...")
        cursor.execute(sqlCrearTabla)
        #conexion.commit()
        print("Tabla factura creada correctamente")
        
        # Insertamos algunos registros de ejemplo en la tabla factura
        # Recorremos la lista sqlInserts que contiene una sentencia Insert por cada elemento
        print("Insertando registros en tabla factura...")
        for sqlInsert in sqlInserts:
            cursor.execute(sqlInsert)
        print("Registros insertados correctamente en tabla factura...")            
        
        # Ejecutamos una consulta SQL de select (query) 
        print("Ejecutando query SQL en tabla factura...")
        cursor.execute(sqlSelect)
        # Mostramos el número de registros devuelto por la consulta SQL
        print("Número de facturas: ", cursor.rowcount)
        # Recorremos cada registro para mostrar sus datos por pantalla
        print("Registros de la tabla factura:")
        registro = cursor.fetchone()
        while registro is not None:
            # Mostramos el campo "codigo" y el campo "importe"
            print("Código: {0} Importe: {1}".format(registro[0], registro[2]))
            # Nos movemos al siguiente registro
            registro = cursor.fetchone()
        
        # Actualizamos (modificamos) un registro de la tabla
        print("Modificando registro en tabla factura...")
        cursor.execute(sqlUpdate)
        print("Registro modificado correctamente...")
        
        # Eliminamos un registro de la tabla
        print("Eliminando un registro en tabla factura...")
        cursor.execute(sqlDelete)
        print("Registro eliminado correctamente...")
        
        # Para finalizar, volvemos a mostrar los registros de la tabla (todos los campos)
        # Para comprobar que se ha actualizado un registro y se ha eliminado otro
        cursor.execute(sqlSelect)
        registro = cursor.fetchone()
        while registro is not None:
            print(registro)
            # Nos movemos al siguiente registro
            registro = cursor.fetchone()
        
        # Cerramos el cursor
        cursor.close

Como siempre, guardaremos este fichero postgresql.py en la misma carpeta que el resto de ficheros.

La aplicación de ejemplo en Python que accede a un servidor PostgreSQL mediante Python

Una vez que tengamos los tres ficheros de la aplicación en la misma carpeta:

  • con.conf: fichero con los datos de acceso al servidor de PostgreSQL.
  • configuracion.py: fichero Python con la función que lee los valores del fichero INI con.conf.
  • postgresql.py: fichero Python con el código para acceso al servidor PostgreSQL y ejecución de las consultas SQL.

Con el resultado:

Conectado correctamente al servidor PostgreSQL [localhost:5432]
Eliminando tabla factura...
Tabla factura eliminada...
Creando tabla factura...
Tabla factura creada correctamente
Insertando registros en tabla factura...
Registros insertados correctamente en tabla factura...
Ejecutando query SQL en tabla factura...
Número de facturas:  5
Registros de la tabla factura:
Código: 1 Importe: $1,555.21
Código: 2 Importe: $100.50
Código: 3 Importe: $1,000.00
Código: 4 Importe: $10.95
Código: 5 Importe: $10.95
Modificando registro en tabla factura...
Registro modificado correctamente...
Eliminando un registro en tabla factura...
Registro eliminado correctamente...
(1, 11, '$1,555.21', datetime.date(2024, 9, 2))
(2, 10, '$100.50', datetime.date(2024, 9, 2))
(3, 11, '$1,000.00', datetime.date(2024, 9, 2))
(4, 20, '$5,000.00', datetime.date(2024, 9, 2))

Descarga de los ficheros Python de acceso a PostgreSQL usados en este tutorial

La descarga de los ficheros con código fuente completo en: