Última actualización: 15 de diciembre de 2023

2.3. Interfaz DB-API

En Python, ofrece el acceso a bases de datos relacionales estandarizado por la especificación Database API (DB-API), actualmente en la versión 2.0 (PEP 249: Python Database API Specification v2.0).

Gracias a esto, se puede acceder a cualquier base de datos utilizando la misma interfaz (ya sea un motor remoto, local, ODBC, etc.). Se puede comparar con DAO, ADO, ADO.NET en el mundo Microsoft, o a JDBC en el mundo Java.

Esta especificación es un conjunto de clases y funciones comunes, estandarizadas, similares para los distintos motores de bases de datos o wrappers alrededor de estos, escritos en Python. Se desarrolla con la finalidad de lograr la consistencia entre todos estos módulos, y ampliar las posibilidades de crear código portable entre las distintas bases de datos.

Advertencia

Cabe aclarar que la API trata principalmente de bases de datos SQL, relacionales, pero implementarla, en lo posible, en motores de base de datos NoSQL no sería conveniente.

Es decir, el mismo código se podría llegar a usar para cualquier base de datos, tomando siempre los recaudos necesarios: (lenguaje SQL estándar, estilo de parámetros soportado, etc.)

Para lograr esto, el manejo de bases de datos en Python siempre sigue los siguientes pasos:

2.3.1. Importar el conector

La forma más comunes de importar la librería de implementación DB-API

1
import databasepackage as base_datos

En general, la única método que se usa directamente en la librería es connect, ya que la mayoría de las demás operaciones se realizan en objetos devueltos después de llamar a this.

2.3.2. Conectar a la base de datos

Se puede conectar a la base de datos usando la método connect del módulo conector a usar.

Los dos objetos de nivel superior cuando se trabaja con DB-API son la conexión y el cursor. Primero obtienes una conexión a una base de datos:

1
conexion = base_datos.connect()

Hay varias formas de especificar los parámetros de conexión de la base de datos. Para la mayoría de las librerías, los valores predeterminados para el método de conexión se conectarán a una base de datos instalada localmente configurada de manera predeterminada.

Algunas bases de datos tienen sus propias opciones, como sqlite3 tiene la opción para una base de datos en memoria no persistente:

1
conexion = sqlite3.connect(":memory:")

2.3.3. Abrir un cursor

Se puede abrir un Cursor a la base de datos usando la método cursor del módulo conector a usar.

A continuación, se obtiene un cursor, que se utilizará para ejecutar comandos transaccionales, consultas SQL y manipulación de datos.

1
cursor = conexion.cursor()

La mejor manera de usar la conexión y el cursor es desde los controladores de recursos. La mayoría de las librerías de bases de datos admiten el manejo de recursos en la conexión, pero solo unas pocas lo admiten en el cursor. Usando with, tanto la conexión como el cursor se cierran después del uso.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
server_params = {
    "database": "nomina",  # Nombre de la base de datos
    "host": "localhost",  # Dirección IP, local o remota del motor de la base de datos
    "port": "5432",  # Puerto de conexión al motor de la base de datos
    "user": "postgres",  # Nombre del usuario de conexión a la base de datos
    "password": "postgres",  # Contraseña del usuario de conexión a la base de datos
}

with base_datos.connect(**server_params) as conexion:
    with conexion.cursor() as cursor:
        pass  # Los comandos SQL van aquí

Si solo se admite el manejo de recursos de conexión, entonces el cursor debe estar envuelto en un bloque de sentencias try / finally para garantizar que el cursor esté cerrado:

1
2
3
4
5
6
7
8
9
with sqlite3.connect(":memory:") as conexion:
    cursor = conexion.cursor()
    try:
        pass  # Los comandos SQL van aquí
    except Exception as e:
        print(e)
    finally:
        if cursor:
            cursor.close()

Si no se admite el manejo de recursos de conexión, ambos tienen métodos close() que deben llamarse como parte de un bloque finalmente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
conexion = sqlite3.connect(":memory:")
cursor = conexion.cursor()
try:
    pass  # Los comandos SQL van aquí
except Exception as e:
    print(e)
finally:
    if conexion:
        conexion.close()
    if cursor:
        cursor.close()

Todas las librerías para bases de datos relacionales que soportan transacciones iniciarán automáticamente una nueva cuando la primera declaración en un cursor nuevo o inmediatamente después de una llamada al método commit() un cursor. Todos los cursores en la conexión se ejecutarán dentro de esa transacción.

Si se utiliza with para el manejo de recursos, la transacción se confirmará al final del bloque. Si administra manualmente los recursos, esta transacción debe confirmarse explícitamente antes de cerrar la conexión, o se revertirá automáticamente. La reversión y la confirmación se realizan con los métodos del mismo nombre:

1
2
conexion.rollback()
conexion.commit()

La confirmación automática también se puede habilitar configurando conexion.autocommit = True en la librería pyscopg2 después de crear la conexión pero antes de la primera ejecución.

El manejo de excepciones se puede hacer con la clase Exception genérica o con las clases específicas para cada librería.

2.3.4. Ejecutar una consulta

Se puede Ejecutar una consulta a la base de datos usando la método execute del cursor del conector a usado.

Un cursor tiene solo dos métodos, execute y executemany, que se utilizan para todas las consultas y DML:

1
cursor.execute("SELECT * FROM empleados")

Para consultas que involucran parámetros, hay cinco estilos de sustitución integrados en los métodos execute:

qmark

1
2
3
4
INSERT INTO empleados
    (nombre, apellido, fecha_nacimiento)
VALUES
    (?, ?, ?)

numeric

1
2
3
4
INSERT INTO empleados
    (nombre, apellido, fecha_nacimiento)
VALUES
    (:1, :2, :3)

named

1
2
3
4
INSERT INTO empleados
    (nombre, apellido, fecha_nacimiento)
VALUES
    (:nombre, :apellido, :fecha_nacimiento)

format

1
2
3
4
INSERT INTO empleados
    (nombre, apellido, fecha_nacimiento)
VALUES
    (%s, %s, %s)

pyformat

1
2
3
4
INSERT INTO empleados
    (nombre, apellido, fecha_nacimiento)
VALUES
    (%(nombre)s, %(apellido)s, %(fecha_nacimiento)s)

Se recomienda encarecidamente utilizar una de estas formas de sustitución en lugar de realizar una construcción o reemplazo directo de cadenas. Usar los operadores de formato integrados de Python no es la forma correcta de hacer esto.

Solo se requiere que cada DB-API admita uno de estos, pero la mayoría de las librerías admiten más de uno.

Si desea indicar al menos uno de los estilos que admite su librería DB-API, cada librería tiene una variable global paramstyle que tiene el valor, por ejemplo, sqlite3.paramstyle

Use marcadores de posición en la declaración y luego pase una tupla para parámetros posicionales o un diccionario para parámetros con nombre.

qmark

1
cursor.execute("SELECT * FROM empleados WHERE nombre = ?", ("Leonardo",))

numeric

1
cursor.execute("SELECT * FROM empleados WHERE nombre = :1", ("Leonardo",))

named

1
cursor.execute("SELECT * FROM empleados WHERE nombre = :nombre", {"nombre": "Leonardo"})

format

1
cursor.execute("SELECT * FROM empleados WHERE nombre = %s", ("Leonardo",))

pyformat

1
2
3
cursor.execute(
    "SELECT * FROM empleados WHERE nombre = %(nombre)s", {"nombre": "Leonardo"}
)

2.3.5. Consultar registros

Se puede Obtener los datos a la base de datos usando la método fetch del cursor del conector a usado o iterar sobre el cursor.

Las llamadas a el método execute siempre devuelven None. En realidad, no se extraen resultados de la base de datos hasta que hacemos una llamada para buscarlos.

Se usan los métodos de búsqueda para obtener resultados de la consulta:

1
2
3
cursor.fetchall()  # devuelve una lista
cursor.fetchone()  # devuelve un objecto
cursor.fetchmany(size=N)  # devuelve una lista

Diferentes bases de datos también proporcionan extensiones propietarias para funciones no especificadas en DB-API. Por ejemplo, psycopg hace que el objeto cursor sea iterable, por lo que puede recorrer de manera escalable un conjunto de resultados potencialmente grande:

1
2
3
4
5
6
cursor.execute(
    "SELECT * FROM empleados WHERE nombre = %(nombre)s", {"nombre": "Leonardo"}
)

for registro in cursor:
    print(registro)

2.3.6. Cerrar el cursor

Se puede cerrar el cursor a la base de datos usando la método close del cursor del conector a usado.

1
conexion.close()

2.3.7. Librerías más populares

Las librerías de bases de datos relacionales más populares son:


Ver también

Consulte la sección de lecturas suplementarias del entrenamiento para ampliar su conocimiento en esta temática.


¿Cómo puedo ayudar?

¡Mi soporte está aquí para ayudar!

Mi horario de oficina es de lunes a sábado, de 9 AM a 5 PM. GMT-4 - Caracas, Venezuela.

La hora aquí es actualmente 7:35 PM GMT-4.

Mi objetivo es responder a todos los mensajes dentro de un día hábil.

Contrata mi increíble soporte profesional