Base de Datos con Python
En este tópico estaremos viendo el funcionamiento con base de datos en Python. Para ello, veremos las librerías necesarias, el uso de sentencias, métodos, etc.. Con respecto a los motores SQLite y MySQL.
Table of Contents
ToggleEl Módulo SQLite3
En este caso no tendremos que instalar nada con pip, ya que, la librería estándar de Python, incluye el módulo sqlite3 que permite la comunicación con bases de datos SQLite.
Para crear una conexión desde un script de Python, utilizamos la función connect() indicando el nombre del archivo (en caso de no existir, es creado automáticamente).
conn = sqlite3.connect(«database.sqlite»)
Sin embargo, para poder generar una consulta, es necesario crear un cursor:
cursor = conn.cursor()
Hecho esto, vía el método execute() procedemos a correr un código SQL.
cursor.execute(«CREATE TABLE empleados (nombre TEXT, edad NUMERIC)»)
Cuando realizamos alguna modificación a través de una consulta (por ejemplo, con cláusulas como CREATE, UPDATE, INSERT, DELETE, etc.) en la información o estructura de alguna tabla de la base de datos, es necesario “guardar los cambios” con una operación llamada commit() y que en Python se realiza a través de la función homónima. Por ejemplo:
conn.commit()
Si cerramos la conexión y no hemos llamado a la función commit(), toda consulta que haya alterado o modificado la base de datos, será desestimada. Por tanto, luego de realizar esto y habiendo terminado la conexión, debemos cerrar la misma:
conn.close()
Agregando Información
En el caso de querer agregar información a una consulta, vamos a crear una tupla llamada “empleados”, cuya estructura será (nombre, edad), y luego para cada una de ellas ejecutaremos una consulta INSERT para añadirla a una tabla. Por ejemplo:
empleados = (
(“Pablo”, 27),
(“Romina”, 22),
(“Mario”, 30)
)
for nombre, edad in empleados:
cursor.execute(“INSERT INTO empleados VALUES (?, ?)”, (nombre, edad))
conn.commit()
Podemos notar que hemos colocado (?, ?) en cuanto a los valores (nombre, edad). Debemos tener en cuenta que, en las consultas nunca se debe utilizar ninguno de los métodos que provee Python para incluir variables dentro de una cadena. En su lugar, se coloca un signo de interrogación por cada valor que se quiera reemplazar, y luego se pasan los objetos dentro de una tupla como segundo argumento.
Esto se debe a una medida de seguridad para evitar inyección de código SQL .
Valor de retorno
Ahora bien, vamos a ejecutar una consulta que retorne todas las filas de la tabla anterior:
cursor.execute(“SELECT * FROM empleados”)
empleados = cursor.fetchall()
print(empleados)
Por lo tanto, se imprimirá en pantalla lo siguiente:
[(“Pablo”, 27), (“Romina”, 22), (“Mario”, 30)]
Como vemos, el output no es algo “normal”. Esto se debe a que la función fetchall() retorna la información devuelta por la consulta en una lista que contiene tuplas, y cada una de éstas corresponde a una fila de la tabla. La lista puede estar vacía si la tabla está vacía o si los criterios de la consulta no coinciden con ninguna fila de la tabla. En el caso de querer retornar solo el primer resultado obtenido, haremos uso de fetchone():
print(cursor.fetchone())
Sin embargo, el resultado obtenido será de una tupla y no de una fila. Ya que solo obtiene una fila de la tabla especificada. En este caso se imprimirá en pantalla:
(“Pablo”, 27)
Del mismo modo, el valor de retorno puede ser None si la tabla está vacía o si la consulta no devolvió ningún resultado.
Excepciones
En el caso de que alguna consulte falle, podemos hacer uso de la función sqlite3.OperationalError. Por ejemplo, la siguiente consulta tiene un error de sintaxis:
cursor.execute(«SELECT FROM empleados»)
Por lo tanto la excepción lanzada será la siguiente:
Traceback (most recent call last):
[…]
cursor.execute(«SELECT FROM empleados»)sqlite3.OperationalError: near «FROM»:syntax error
Teniendo esto en cuenta, recordemos que podemos capturar dichas excepciones con try/except. Por ejemplo:
try:
cursor.execute(«SELECT FROM empleados»)
except sqlite3.OperationalError:
print(«La consulta no se ha ejecutado correctamente.»)
El módulo Pymysql
Este módulo se utiliza para comunicarse con base de datos MySQL, de la misma forma que sqlite3 con SQLite. Ambos adhieren a la DB-API, por tanto sus estructuras son muy parecidas.
Podemos ejecutar este módulo de la siguiente manera:
pip install pymysql
Ahora bien, si queremos conectarnos a MySQL, usaremos la función connect() pero esta vez indicaremos la dirección y puerto del servidor, nombre de la base de datos, usuario y contraseña:
import pymysql
conn = pymysql.connect (
host=”localhost”
port=num_of_port
user=”username”
passwd=”password”
db=”name_of_db”
)
Tener en cuenta
Cuando llamamos a una función y, en general, para cualquier expresión encerrada entre paréntesis, es posible especificar los argumentos en distintas líneas para mejorar la legibilidad. También podemos indicarle a Python que seguiremos un código en la próxima línea a través del caracter \ (barra invertida).
El resto de las funciones son similares a las de SQLite. La función conn.cursor() retorna un cursor a partir del cual podemos invocar a execute() para ejecutar consultas. Cabe mencionar que esta última funciona utiliza los caracteres %s en lugar del signo de interrogación (?) para incluir objetos de Python en una consulta. Por ejemplo:
for nombre, edad in empleados:
cursor.execute(“INSERT INTO empleados VALUES (%s, %s)”, (nombre, edad))
Excepción en Pymysql
En el caso de pymysql, la excepción lanzada ante un error de sintaxis es pymysql.ProgrammingError. Por ejemplo, teniendo en cuenta la sentencia errónea como vimos anteriormente:
cursor.execute(“SELECT FROM empleados”)
El resultado sería el siguiente:
Traceback (most recent call last):
[…]
pymysql.err.ProgrammingError: (1064, «You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘FROM personas’ at line 1″)
Esto también sucede cuando intentamos acceder a una tabla inexistente.
En algunos casos, la excepción que nos devuelve es pymysql.err.InternalError. Esto sucede cuando hay una fila inexistente en la tabla, o también, cuando especificamos una tabla que ya existe. Por ejemplo:
cursor.execute(“CREATE TABLE empleados (nombre VARCHAR(50), edad INT)”)
La forma de capturar dicha excepción sería de la siguiente manera:
try:
cursor.execute(“SELECT apellido FROM empleados”)
except: pymysql.err.InternalError:
print(“La consulta no se ha ejecutado correctamente!”)
Para capturar la primer excepción mencionada simplemente debemos colocar:
except: pymysql.Programming.Error
Si deseas aprender o ejercitar estos conocimientos, puedes verificar mi repositorio de github, o también, ver el siguiente artículo donde se explica la inyección y protección SQL en Python.