Introducción
Recientemente vimos cómo trabajar con Python3 y SQLite3. Hoy veremos cómo combinar Python3 y MySQL para insertar, editar, eliminar y mostrar registros en esta base de datos tan popular. Así que veamos este tutorial fácil con ejemplos y demostración.
Para conectar MySQL y Python 3 vamos a utilizar el paquete llamado PyMySQL.
Nota: también he escrito tutoriales para conectar Python con SQL Server y con PostgreSQL.
Descargar el código fuente
Si lo deseas, puedes descargar todos los archivos que contienen el código fuente para conectar Python con MySQL en mi GitHub.
Requisitos
- Python versión 3 y pip
- MySQL (tutorial con XAMPP aquí)
Instalar módulo PyMySQL
Para instalar lo que nos permitirá conectarnos con MySQL desde Python 3 ejecutamos el siguiente comando:
pip install PyMySQL
En caso de que ese comando no llegara a funcionar, podemos usar:
python -m pip install PyMySQL
Si incluso así sigue sin funcionar, recuerda configurar e instalar Python. Cuando instales correctamente la librería, se mostrará algo así:
Crear base de datos en MySQL
Para poder trabajar con Python 3 y MySQL debemos tener una base de datos en éste último. Para ello nos conectamos a nuestro servidor de MySQL y creamos una base de datos. Durante el tutorial trabajaremos con una base de datos de películas que tendrá una tabla llamada también películas, y sólo eso.
En mi caso voy a utilizar la CLI de MySQL. La definición de la tabla y la creación de la base de datos queda así:
CREATE DATABASE peliculas;
USE peliculas;
CREATE TABLE IF NOT EXISTS peliculas(
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
titulo VARCHAR(255) NOT NULL,
anio SMALLINT NOT NULL,
PRIMARY KEY(id)
);
Cuando lo ejecuto en la CLI de MySQL se ve así:
Puedes usar phpmyadmin o la interfaz de MySQL workbench, tú decide. Sólo ten en cuenta que la base de datos y la tabla deben estar creadas y funcionando.
Primera conexión
Antes de hacer el CRUD vamos a ver si nos podemos conectar a la base de datos. Para ello ponemos este fragmento de código en un try/except:
import pymysql
try:
conexion = pymysql.connect(host='localhost',
user='root',
password='',
db='peliculas')
print("Conexión correcta")
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
print("Ocurrió un error al conectar: ", e)
Aquí hay unos parámetros que debemos tener en cuenta.
- host: el host en donde nuestro servidor MySQL escucha. Normalmente es localhost o 127.0.0.1 pero igualmente podría ser otro, basta con poner la ip
- user: el usuario que puede administrar la base de datos
- password: la contraseña del usuario. Si está vacía dejamos las comillas vacías
- db: el nombre de la base de datos a la que intentamos conectarnos
Si todo va bien, al ejecutar el script debe mostrar el mensaje:
Conexión correcta
En caso de que no, se mostrarán errores. Aquí abajo dejo los más comunes.
En el primer caso es porque puse localhosts en lugar de localhost. Esto también pasará si ponemos una IP en donde el servidor no esté escuchando.
En el segundo caso puse un usuario que no está registrado o que no tiene permiso para esa base de datos.
El el tercer caso puse el nombre de una base de datos que no existe.
Continuemos entonces.
Insertar datos en MySQL desde Python 3
Antes de continuar cabe mencionar que los ejemplos aquí son 100 % seguros. Es decir, nuestras consultas prevendrán las inyecciones SQL.
Para insertar una película hacemos esto:
import pymysql
try:
conexion = pymysql.connect(host='localhost',
user='root',
password='',
db='peliculas')
try:
with conexion.cursor() as cursor:
consulta = "INSERT INTO peliculas(titulo, anio) VALUES (%s, %s);"
#Podemos llamar muchas veces a .execute con datos distintos
cursor.execute(consulta, ("Volver al futuro 1", 1985))
cursor.execute(consulta, ("Ready Player One", 2018))
cursor.execute(consulta, ("It", 2017))
cursor.execute(consulta, ("Pulp Fiction", 1994))
conexion.commit()
finally:
conexion.close()
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
print("Ocurrió un error al conectar: ", e)
Como vemos, necesitamos tener la conexión. Y luego usamos un cursor para ejecutar nuestra consulta sobre la misma.
Es importante notar que usamos %s en lugar del valor real, y luego ponemos los verdaderos datos en la llamada a .execute del cursor. Esto es para que sea una consulta segura y las variables sean escapadas en caso de que un usuario malicioso quisiera aprovechar esa vulnerabilidad.
Más abajo hacemos un commit. Esto es para guardar los cambios que hicimos a la base de datos, si no llamamos a este método ninguno de nuestros cambios se reflejará.
Todo eso lo encerramos en un bloque try/finally (aparte del que pertenece a la conexión) y siempre cerramos la conexión. Así, si hay un problema con la inserción, la conexión no quedará abierta.
Consultar datos de MySQL con Python 3
Ya vimos cómo insertar, ahora vamos a ver cómo listar o consultar. Para ello usamos el siguiente código:
import pymysql
try:
conexion = pymysql.connect(host='localhost',
user='root',
password='',
db='peliculas')
try:
with conexion.cursor() as cursor:
# En este caso no necesitamos limpiar ningún dato
cursor.execute("SELECT id, titulo, anio FROM peliculas;")
# Con fetchall traemos todas las filas
peliculas = cursor.fetchall()
# Recorrer e imprimir
for pelicula in peliculas:
print(pelicula)
finally:
conexion.close()
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
print("Ocurrió un error al conectar: ", e)
Siempre usamos el cursor. Ahora llamamos al método fetchall que traer todas las filas. No deberíamos usarlo para grandes datos, pues si hay 1000 filas traerá todas.
Si quisiéramos traer una por una podríamos llamar al método fetchone. En fin, al ejecutar el script sale esto:
Consultar datos de MySQL con Python 3 usando WHERE
Para hacer una consulta con WHERE tenemos que limpiar los datos para prevenir inyecciones. Aquí un ejemplo en donde consultamos las películas cuyo año sea mayor que el 2000.
import pymysql
try:
conexion = pymysql.connect(host='localhost',
user='root',
password='',
db='peliculas')
try:
with conexion.cursor() as cursor:
consulta = "SELECT id, titulo, anio FROM peliculas WHERE anio > %s;"
cursor.execute(consulta, (2000))
# Con fetchall traemos todas las filas
peliculas = cursor.fetchall()
# Recorrer e imprimir
for pelicula in peliculas:
print(pelicula)
finally:
conexion.close()
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
print("Ocurrió un error al conectar: ", e)
Lo que hay que notar es que siempre usamos los placeholders %s en lugar de concatenar valores. Al ejecutar eso, este es el resultado:
Editar filas de MySQL con Python 3
Veamos ahora cómo hacer un update o una edición de datos. Igualmente usaremos el cursor, y prepararemos la sentencia para que la misma sea segura.
Lo que hace el siguiente código es cambiar el nombre a “Ready Player One: comienza el juego” en donde la película tenga el id 2.
import pymysql
try:
conexion = pymysql.connect(host='localhost',
user='root',
password='',
db='peliculas')
try:
with conexion.cursor() as cursor:
consulta = "UPDATE peliculas SET titulo = %s WHERE id = %s;"
nuevo_titulo = "Ready Player One: comienza el juego"
id_editar = 2
cursor.execute(consulta, (nuevo_titulo, id_editar))
# No olvidemos hacer commit cuando hacemos un cambio a la BD
conexion.commit()
finally:
conexion.close()
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
print("Ocurrió un error al conectar: ", e)
Siempre tenemos que usar placeholders, nunca concatenar. Y cuando hacemos una operación que modifique la base de datos (insert, update, delete) tenemos que hacer commit para reflejar los cambios.
En la imagen podemos ver que primero listamos los datos y el título de la película es el antiguo. Luego ejecutamos el script para actualizar, y al volver a listar observamos que la película tiene un nuevo nombre:
Eliminar filas o registros de MySQL con Python 3
Para terminar con este tutorial vamos a ver cómo eliminar datos. Es exactamente igual que cuando hacemos un update o insert.
El siguiente fragmento de código elimina las películas que se hayan estrenado antes del año 2000:
import pymysql
try:
conexion = pymysql.connect(host='localhost',
user='root',
password='',
db='peliculas')
try:
with conexion.cursor() as cursor:
consulta = "DELETE FROM peliculas WHERE anio < %s;"
anio = 2000
cursor.execute(consulta, (anio))
# No olvidemos hacer commit cuando hacemos un cambio a la BD
conexion.commit()
finally:
conexion.close()
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
print("Ocurrió un error al conectar: ", e)
Para comprobar que realmente está eliminando primero listamos las películas, luego ejecutamos la eliminación y finalmente volvemos a listar.
Al final sólo quedan 2 películas.
Conclusión
Así es como terminamos este tutorial de Python 3 y MySQL o MariaDB. Aquí dejo algunas referencias
- Especificación de la API de la base de datos: https://www.python.org/dev/peps/pep-0249/
- Repositorio oficial de PyMySQL: https://github.com/PyMySQL/PyMySQL
Excelente
Hola, gracias muy buena la información!! quería saber si tienes algo o me puedes recomendar para trabajar mysql desde formularios seria hacer el crud pero desde el navegador web?
Puede usar HTML y JavaScript del lado del cliente (si quiere, con un framework), y la siguiente API: https://parzibyte.me/blog/2020/11/10/api-rest-python-flask-sqlite3/
Gracias Colega. El unico sitio despues de ver 5 y con diferentes librerias que no funcionaban. Tu ejempolo es claro y funciona. Mil gracias amigo. 27.10.22
Gracias por sus comentarios. Saludos y éxito!
porque utilizar esta libreria y no utilizar
import mysql.connector
?
Hola. Usted puede usar cualquier librería o método que prefiera, aquí expongo lo que yo prefiero usar.
Saludos!
Muchísimas gracias por compartir tanta y tan buena información parzibyte.
Con lo que cuesta mantener un blog!!!
El tuyo es una maravilla.
Gracias por sus comentarios 🙂
Buenas Tardes
Interesante y útil sus apuntes
Por favor, como haría para vaciar el contenido de una tabla en QT5
Hola, simplemente al arreglo de datos hay que volcarlo sobre la tabla. Espero hacer un tutorial sobre ello en el futuro, pues es muy largo de explicar en un comentario.
Saludos 🙂
muy buen tutorial para conocer algo muy basico pero escencial que tienen todas las aplicaciones, las formas de manejar los datos un una base de datos.
Hola,
Muchísimas gracias, muy interesante. Dos cosas:
Creo que hay una errata en “Primera conexión” > en la línea 6: “db=’peliculass’)”. Será “db=’peliculas’)”, con una “s”, ¿no?
Y a mi me da un error: Ocurrió un error al conectar: (1049, “Unknown database ‘fondos'”)
¿hay que poner la bdd.tabla? No me sale de ninguna fomra
Hola. Gracias por tus comentarios. Sobre la errata que mencionas, lo había puesto así para generar un error pero olvidé cambiarlo al subirlo; ya lo he corregido.
Sobre el segundo: debes crear una base de dato llamada fondos (ya que no se crea automáticamente), recuerda que una base de datos tiene tablas dentro de la misma.
Si no sabes mucho sobre MySQL puedes ver unos ejercicios: https://parzibyte.me/blog/2018/02/06/ejercicios-resueltos-consultas-sql-mysql/
O sobre la CLI: https://parzibyte.me/blog/2018/09/19/primeros-pasos-con-la-cli-de-mysql/
gracias parzibyte
Es un placer ayudar. Te invito a seguirme en mis redes sociales y suscribirte para estar al tanto de mi contenido 🙂
Tantas páginas, videos y cosas vistas, y esta si que es la más completa de todas y sobre todo explica el por qué usar %s en lugar de concatenar. Me gustaría saber si hay forma de poder reutilizar el código así como en php, es decir, hacer un require_once ‘db.php’ para luego un db = new Conexion , es decir, tener la conexión en un archivo para ser llamada en los diferentes archivos .py donde vaya a manipular datos. Muchas Gracias por tu tiempo y dedicación!!
Gracias por tus comentarios 🙂
Nota: el código pierde las tabulaciones al pegarlo aquí, pero sirve para ejemplificar, no lo copies directamente.
Respondiendo a tu duda, claro que sí, puedes importar tus módulos en Python. Por ejemplo, pega el código de conexión en un archivo llamado base_de_datos.py que residirá junto a tu código principal:
import pymysql def conectar(): try: conexion = pymysql.connect(host='localhost', user='root', password='', db='peliculas') return conexion except (pymysql.err.OperationalError, pymysql.err.InternalError) as e: print("Ocurrió un error al conectar: ", e) return False
Ahí definimos a la función conectar. Luego, en tu código principal importa la función y llámala:
from base_de_datos import conectar conexion = conectar()
La sintaxis es “from tuArchivo import tuFuncion”. Ahora ya puedes usar la conexión normalmente, suponiendo que fue exitosa.
Más información de módulos: https://docs.python.org/2/tutorial/modules.html