# Almacenamiento y serialización de datos con la biblioteca estándar de Python: `json`, `pickle`, `csv` Para guardar datos en archivos o enviarlos por la red, se necesita **serialización**. Python ofrece tres herramientas estándar, cada una con un enfoque distinto: **`json`**, **`pickle`**, **`csv`**. ![Formatos de entrega de datos](/media/editor_temp/6/82b2d285-16b0-473a-b88a-cd9a6f6582f2.png) * **`json`**: formato de texto legible por humanos, excelente para intercambio entre lenguajes. * **`pickle`**: formato binario que guarda objetos de Python tal cual, potente pero con riesgos de seguridad. * **`csv`**: formato de texto simple para datos tabulares, muy versátil. En este artículo organizamos la elección de cada módulo según el tipo de datos y el destino. --- ## 1. JSON {#sec-c0452ee3f8b9} ### 1.1 Visión general {#sec-573894aef250} JSON (JavaScript Object Notation) es **basado en texto** y **independiente de lenguaje**. Se usa ampliamente en archivos de configuración, respuestas/solicitudes de API y logs. En Python se maneja con el módulo `json`. ### 1.2 API principal (lo más usado) {#sec-7388e1478aff} * `json.dump(obj, fp, ...)` / `json.load(fp, ...)` : guardar/leer desde archivo. * `json.dumps(obj, ...)` / `json.loads(s, ...)` : convertir a/desde cadena. Opciones útiles: * `ensure_ascii=False` – guarda caracteres internacionales sin escapar. * `indent=2` – formato legible. * `default=...` – función para convertir tipos desconocidos. ### 1.3 Ejemplo básico {#sec-57d0c0653337} ```python import json data = { "name": "Alice", "age": 30, "skills": ["Python", "Data Science"] } with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) with open("data.json", "r", encoding="utf-8") as f: loaded = json.load(f) print(loaded) ``` ### 1.4 Solución sencilla a la limitación de tipos {#sec-a43d0fe8a199} JSON admite nativamente `dict`, `list`, `str`, `int/float`, `bool`, `None`. Para tipos como `datetime`, se puede usar `default`. ```python import json from datetime import datetime, timezone payload = {"created_at": datetime.now(timezone.utc)} def to_jsonable(obj): if isinstance(obj, datetime): return obj.isoformat() raise TypeError(f"Not JSON serializable: {type(obj)!r}") s = json.dumps(payload, default=to_jsonable, ensure_ascii=False) print(s) ``` ### 1.5 Ventajas y desventajas {#sec-667d6fad184b} **Ventajas** * Intercambio entre lenguajes. * Texto: depuración y control de versiones. * No ejecuta código al cargar. **Desventajas** * Expresión limitada de tipos (datetime, set, Decimal, binario). * En datos grandes, puede ser menos eficiente. --- ## 2. Pickle {#sec-7417b1955ccc} ### 2.1 Visión general {#sec-1889607ea8cb} `pickle` serializa objetos de Python en **binario**. Al cargar, se recupera un objeto casi idéntico. Es útil cuando: * Se desea conservar objetos complejos (clases, estructuras anidadas, modelos entrenados). * No se necesita interoperabilidad con otros lenguajes. Evita usarlo cuando: * La fuente no es confiable (`pickle.load()` puede ejecutar código). * Se necesita compartir con sistemas no Python. --- ### 2.2 API principal (los 4 más usados) {#sec-a0a97fe87a25} * `pickle.dump(obj, file, protocol=...)` * `pickle.load(file)` * `pickle.dumps(obj, protocol=...)` * `pickle.loads(data)` Ejemplo típico de archivo: ```python import pickle data = {"a": [1, 2, 3], "b": ("x", "y")} with open("data.pkl", "wb") as f: pickle.dump(data, f) with open("data.pkl", "rb") as f: loaded = pickle.load(f) print(loaded) ``` --- ### 2.3 ¿Qué es `protocol` y por qué importarlo? {#sec-1f8e5565848c} `protocol` define la versión del formato de pickle. El valor por defecto es el más adecuado para la versión actual de Python. * Si se necesita compatibilidad con versiones antiguas, se debe fijar un protocolo bajo. * Para optimizar tamaño y velocidad, se suele usar `pickle.HIGHEST_PROTOCOL`. ```python import pickle with open("data.pkl", "wb") as f: pickle.dump({"x": 1}, f, protocol=pickle.HIGHEST_PROTOCOL) ``` --- ### 2.4 Precaución real (importante) {#sec-007b70a5e9ec} `pickle.load()` ejecuta el código embebido en el pickle. Por eso, **nunca cargues un pickle de origen desconocido**. * Si el objetivo es compartir, opta por `json` u otro formato de texto. --- ### 2.5 Ventajas y desventajas {#sec-bbd5a24bec31} **Ventajas** * Guarda prácticamente cualquier objeto de Python. * Generalmente más rápido que `json` para objetos complejos. **Desventajas** * Riesgo de seguridad. * No interoperable con otros lenguajes. * Cambios en la definición de clases pueden romper pickles antiguos. --- ## 3. CSV {#sec-99e590b24e50} ### 3.1 Visión general {#sec-1265cc44a461} CSV (Comma-Separated Values) es el formato más sencillo para datos tabulares. Se usa en hojas de cálculo, exportaciones e importaciones de datos y logs simples. ### 3.2 API principal (lo más usado) {#sec-5b2e4c37cce5} * `csv.reader`, `csv.writer` – listas. * `csv.DictReader`, `csv.DictWriter` – diccionarios (más cómodo). ### 3.3 Ejemplo con `DictWriter`/`DictReader` {#sec-524921270351} ```python import csv data = [ {"name": "Alice", "age": 30, "city": "Seoul"}, {"name": "Bob", "age": 25, "city": "Busan"}, ] with open("people.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["name", "age", "city"]) writer.writeheader() writer.writerows(data) with open("people.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) loaded = list(reader) print(loaded) ``` ### 3.4 Puntos de precaución (3) {#sec-3db1b7ed8444} 1. **Usar `newline=""`** – evita saltos de línea dobles en Windows. 2. **Todos los valores son cadenas** – conviene convertir tipos manualmente. 3. **Separadores y comillas dentro de los datos** – el módulo `csv` maneja estos casos. ### 3.5 Ventajas y desventajas {#sec-6a8ca4891a8e} **Ventajas** * Muy ligero y ampliamente soportado. * Ideal para datos tabulares simples. **Desventajas** * No representa estructuras anidadas. * Falta de información de tipo. --- ## 4. Comparación y guía de selección {#sec-6304ec188cc0} | Característica | JSON | Pickle | CSV | |----------------|------|--------|-----| | Compatibilidad | Muy buena | Solo Python | Muy buena | | Legibilidad | Alta | Baja (binario) | Alta | | Expresión de tipos | Limitada | Alta | Limitada | | Seguridad | Relativamente segura | Precaución necesaria | Relativamente segura | | Estructura | Árbol (anidado) | Objeto completo | Tabla (fila/columna) | **Resumen rápido** * Intercambio entre sistemas → `json`. * Guardar objetos de Python íntegros → `pickle` (con precaución). * Exportar/leer datos tabulares → `csv`. --- ## 5. Guardar y cargar los mismos datos con los tres formatos {#sec-21f8c2a6d6c9} ```python import json, pickle, csv data = [ {"id": 1, "name": "Alice", "score": 95.5}, {"id": 2, "name": "Bob", "score": 88.0}, ] # 1) JSON with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) with open("data.json", "r", encoding="utf-8") as f: json_loaded = json.load(f) # 2) Pickle with open("data.pkl", "wb") as f: pickle.dump(data, f) with open("data.pkl", "rb") as f: pickle_loaded = pickle.load(f) # 3) CSV with open("data.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["id", "name", "score"]) writer.writeheader() writer.writerows(data) with open("data.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) csv_loaded = [ {"id": int(row["id"]), "name": row["name"], "score": float(row["score"])} for row in reader ] print(json_loaded) print(pickle_loaded) print(csv_loaded) ``` * CSV requiere conversión de tipos al leer. * Pickle es cómodo pero exige cuidado con la fuente. --- ## 6. Conclusión {#sec-f88db3766ed6} Con la biblioteca estándar de Python, la serialización y el almacenamiento de datos cubren una amplia gama de necesidades. * Si el objetivo es **intercambio** y **legibilidad**, elige `json`. * Si necesitas **conservar objetos de Python** tal cual, usa `pickle` (con precaución). * Si trabajas con **datos tabulares simples**, `csv` es la opción más ligera. Selecciona el módulo que mejor se adapte a la forma y al propósito de tus datos, y obtendrás una solución rápida y limpia.