Conectar Python con MySQL permite guardar información de forma persistente, consultar registros, actualizar datos y construir aplicaciones que trabajan con varios usuarios. MySQL es una base de datos relacional ampliamente utilizada, mientras que Python ofrece bibliotecas sencillas para ejecutar consultas y procesar resultados.
En esta guía aprenderás a preparar el entorno, proteger las credenciales, abrir una conexión, crear tablas, insertar, consultar, actualizar y eliminar registros, utilizar consultas parametrizadas, controlar transacciones y organizar el código para que sea mantenible.
Qué necesitas antes de empezar
Debes tener un servidor MySQL accesible y una base de datos creada. También necesitas un usuario con los permisos mínimos necesarios. Evita trabajar con la cuenta administrativa principal dentro de una aplicación.
La documentación oficial de MySQL Connector/Python explica instalación, conexiones, cursores y manejo de errores. Para una capa de abstracción más amplia, consulta también la documentación oficial de SQLAlchemy.
Crear un entorno virtual
Aísla las dependencias del proyecto:
python -m venv .venvActiva el entorno e instala el conector:
# Windows
.venv\Scripts\activate
# macOS o Linux
source .venv/bin/activate
python -m pip install mysql-connector-python python-dotenvLa guía de entornos virtuales en Python explica cómo seleccionar el intérprete correcto en el editor y evitar conflictos entre proyectos.
Crear la base y el usuario
Desde una herramienta administrativa autorizada, crea una base y un usuario limitado. Ajusta los nombres y la contraseña a tu entorno:
CREATE DATABASE tienda CHARACTER SET utf8mb4;
CREATE USER 'app_tienda'@'localhost'
IDENTIFIED BY 'una_contrasena_segura';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE
ON tienda.* TO 'app_tienda'@'localhost';
FLUSH PRIVILEGES;En producción, concede únicamente las operaciones que la aplicación realmente necesita.
Guardar las credenciales fuera del código
No escribas usuario y contraseña directamente dentro del archivo Python. Crea un archivo .env:
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_DATABASE=tienda
MYSQL_USER=app_tienda
MYSQL_PASSWORD=una_contrasena_seguraAñade .env al .gitignore. La guía de variables de entorno en Python muestra cómo separar configuración y código.
Abrir una conexión
import os
import mysql.connector
from dotenv import load_dotenv
load_dotenv()
connection = mysql.connector.connect(
host=os.getenv("MYSQL_HOST"),
port=int(os.getenv("MYSQL_PORT", "3306")),
database=os.getenv("MYSQL_DATABASE"),
user=os.getenv("MYSQL_USER"),
password=os.getenv("MYSQL_PASSWORD"),
)
print("Conexión abierta:", connection.is_connected())
connection.close()La conexión debe cerrarse aunque una operación falle. Puedes envolverla en una función o utilizar un bloque try/finally.
Crear una tabla
import mysql.connector
def create_products_table(connection):
sql = """
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(150) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INT NOT NULL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""
with connection.cursor() as cursor:
cursor.execute(sql)
connection.commit()Los nombres, tamaños y restricciones deben reflejar las reglas reales del proyecto. El tipo DECIMAL es más adecuado que un punto flotante para valores monetarios.
Insertar datos con parámetros
Nunca construyas una consulta concatenando texto proporcionado por el usuario. Utiliza parámetros:
def create_product(connection, name, price, stock):
sql = """
INSERT INTO products (name, price, stock)
VALUES (%s, %s, %s)
"""
with connection.cursor() as cursor:
cursor.execute(sql, (name, price, stock))
product_id = cursor.lastrowid
connection.commit()
return product_idLas consultas parametrizadas separan la instrucción SQL de los valores y reducen el riesgo de inyección. Aun así, valida longitudes, rangos y tipos antes de guardar.
Insertar varios registros
products = [
("Teclado", 89.90, 12),
("Ratón", 35.50, 25),
("Monitor", 249.00, 6),
]
sql = """
INSERT INTO products (name, price, stock)
VALUES (%s, %s, %s)
"""
with connection.cursor() as cursor:
cursor.executemany(sql, products)
connection.commit()Para importar datos desde una hoja o archivo, revisa la guía de archivos CSV con Python. Conviene limpiar y validar el contenido antes de enviarlo a la base.
Consultar registros
def list_products(connection):
sql = """
SELECT id, name, price, stock
FROM products
ORDER BY name
"""
with connection.cursor(dictionary=True) as cursor:
cursor.execute(sql)
return cursor.fetchall()
for product in list_products(connection):
print(
product["id"],
product["name"],
product["price"],
product["stock"],
)Un cursor con dictionary=True devuelve cada fila como diccionario. Para conjuntos de resultados muy grandes, evita cargar todo en memoria y procesa las filas por lotes.
Buscar un registro por ID
def find_product(connection, product_id):
sql = """
SELECT id, name, price, stock
FROM products
WHERE id = %s
"""
with connection.cursor(dictionary=True) as cursor:
cursor.execute(sql, (product_id,))
return cursor.fetchone()La coma en (product_id,) crea una tupla con un elemento. Si el resultado es None, el registro no existe.
Actualizar datos
def update_stock(connection, product_id, stock):
sql = """
UPDATE products
SET stock = %s
WHERE id = %s
"""
with connection.cursor() as cursor:
cursor.execute(sql, (stock, product_id))
changed = cursor.rowcount
connection.commit()
return changedComprueba rowcount para saber si alguna fila fue afectada. La validación de stock debe impedir valores negativos si esa es una regla de la aplicación.
Eliminar un registro
def delete_product(connection, product_id):
sql = "DELETE FROM products WHERE id = %s"
with connection.cursor() as cursor:
cursor.execute(sql, (product_id,))
changed = cursor.rowcount
connection.commit()
return changedLas eliminaciones definitivas requieren cuidado. En algunos sistemas es preferible añadir un campo de estado y conservar el historial.
Transacciones y rollback
Una transacción agrupa varias operaciones. Si una falla, puedes revertir todo:
from mysql.connector import Error
try:
connection.start_transaction()
with connection.cursor() as cursor:
cursor.execute(
"UPDATE products SET stock = stock - %s WHERE id = %s",
(2, 1),
)
cursor.execute(
"INSERT INTO sales (product_id, quantity) VALUES (%s, %s)",
(1, 2),
)
connection.commit()
except Error:
connection.rollback()
raiseEl manejo de excepciones debe conservar el error original. La guía de try y except en Python explica encadenamiento, else y finally.
Crear una función de conexión reutilizable
def open_connection():
required = [
"MYSQL_HOST",
"MYSQL_DATABASE",
"MYSQL_USER",
"MYSQL_PASSWORD",
]
missing = [name for name in required if not os.getenv(name)]
if missing:
raise RuntimeError(
"Falta configuración: " + ", ".join(missing)
)
return mysql.connector.connect(
host=os.getenv("MYSQL_HOST"),
port=int(os.getenv("MYSQL_PORT", "3306")),
database=os.getenv("MYSQL_DATABASE"),
user=os.getenv("MYSQL_USER"),
password=os.getenv("MYSQL_PASSWORD"),
)Separar la conexión de las operaciones CRUD facilita las pruebas y permite cambiar la configuración sin modificar cada consulta.
MySQL Connector o SQLAlchemy
El conector directo es apropiado cuando quieres controlar el SQL y el proyecto es pequeño. SQLAlchemy ofrece motores, agrupación de conexiones, construcción de consultas y un ORM. Ninguna opción elimina la necesidad de comprender transacciones, índices y seguridad.
Para una alternativa incluida con Python y sin servidor separado, consulta la guía de SQLite con Python.
Errores frecuentes
- Guardar contraseñas dentro del repositorio.
- Usar la cuenta root desde la aplicación.
- Concatenar valores directamente en SQL.
- Olvidar
commit()después de modificar datos. - No ejecutar
rollback()cuando una transacción falla. - Abrir una conexión nueva para cada fila.
- No crear índices para búsquedas frecuentes.
- Ignorar zonas horarias, codificación y precisión decimal.
Conclusión
Una integración segura entre Python y MySQL utiliza credenciales externas, usuarios limitados, consultas parametrizadas, transacciones claras y conexiones correctamente cerradas. Empieza con operaciones CRUD pequeñas, valida cada entrada y separa el acceso a datos de la interfaz de la aplicación. Cuando el proyecto crezca, añade migraciones, agrupación de conexiones, registros y pruebas automatizadas.

