En una entrada anterior vimos cómo crear paso a paso un Data Lake en Azure, configurando los permisos y contenedores necesarios. En esta ocasión, vamos a dar el siguiente paso natural: cargar datos desde Python a Azure Data Lake Storage Gen2, utilizando las librerías oficiales de Microsoft.
El objetivo de este tutorial es mostrar cómo un servicio o script en Python puede enviar datos automáticamente al Data Lake, ya sea información generada por un proceso ETL, resultados de un modelo de Machine Learning o registros recogidos en tiempo real desde una API.
Este enfoque es muy útil cuando:
A lo largo de esta guía veremos:
pandas y faker.Al finalizar, tendrás un script funcional en Python capaz de enviar datos al Data Lake de Azure de forma segura y automatizada.
Tabla de contenidos
Para cargar datos desde Python a Azure Data Lake vamos a utilizar cuatro paquetes principales:
Para instalar los paquetes, simplemente ejecuta el siguiente comando en la terminal o PowerShell:
pip install azure-storage-blob pandas pyarrow faker
Para poder conectarte a tu Azure Data Lake Storage Gen2, necesitas autenticarte ante el servicio. La forma más sencilla para es usar la Connection String, que puedes obtener desde el portal de Azure:
DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net).Importante: Nunca incluyas esta cadena directamente en tu código fuente ni la subas a un repositorio. En su lugar, guárdala como una variable de entorno del sistema.
Puedes definir la variable de entorno desde PowerShell:
setx AZURE_STORAGE_CONNECTION_STRING "DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"
Después de ejecutar el comando, reinicia tu terminal o tu editor (VS Code, por ejemplo) para que la variable esté disponible.
Puedes verificar que se ha guardado correctamente con:
echo $env:AZURE_STORAGE_CONNECTION_STRING
En distribuciones como Ubuntu o Debian, puedes establecer la variable de entorno temporalmente en el terminal actual:
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"
Si quieres que se cargue automáticamente cada vez que inicies sesión, añádela al archivo ~/.bashrc o ~/.zshrc:
echo 'export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"' >> ~/.bashrc source ~/.bashrc
Para comprobarla:
echo $AZURE_STORAGE_CONNECTION_STRING
El proceso es muy similar al de Linux. Si usas zsh (el shell por defecto en macOS):
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"
Para hacerla persistente:
echo 'export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"' >> ~/.zshrc source ~/.zshrc
Puedes verificar que la variable está disponible con:
echo $AZURE_STORAGE_CONNECTION_STRING
Antes de continuar, es importante comprobar que los sciprts de Python puede acceder a la variable de entorno con las cadena de conexión:
import os
conn_str = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
if conn_str:
print("Conexión con Azure configurada correctamente.")
else:
print("No se encontró la variable de entorno AZURE_STORAGE_CONNECTION_STRING.") Si todo es correcto, se debería ver el mensaje: ”Conexión con Azure configurada correctamente.” Si no es así, es necesario revisar los pasos anteriores antes de continuar.
Una vez configurada la cadena de conexión al Data Lake, el siguiente paso es establecer la conexión con el servicio de almacenamiento y acceder al contenedor donde guardaremos los datos. En este ejemplo, utilizaremos un contenedor llamado raw, que normalmente corresponde a la capa donde se almacenan los datos en bruto antes de ser procesados.
Para realizar la conexión usaremos la clase BlobServiceClient del paquete azure-storage-blob. Esta clase permite interactuar con el servicio de Azure Blob Storage (o Data Lake Storage Gen2) de forma sencilla, creando contenedores, subiendo archivos o listando su contenido.
El siguiente fragmento de código muestra cómo conectar al servicio, obtener el cliente del contenedor y crearlo si no existe:
from azure.storage.blob import BlobServiceClient
# Leer la cadena de conexión
connect_str = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
# Crear cliente de servicio
blob_service_client = BlobServiceClient.from_connection_string(connect_str)
# Nombre del contenedor
container_name = "raw"
container_client = blob_service_client.get_container_client(container_name)
# Crear el contenedor si no existe
try:
container_client.create_container()
print(f"Contenedor '{container_name}' creado correctamente.")
except Exception:
print(f"El contenedor '{container_name}' ya existe.") Si todo se ejecuta correctamente, verás un mensaje indicando que el contenedor fue creado o que ya existía previamente.
Consejo: Este bloque de código suele usarse solo la primera vez que se inicializa el Data Lake o durante la configuración del entorno. En un entorno de producción o dentro de un pipeline automatizado, normalmente se asume que el contenedor de destino ya existe, y solo se establece la conexión para subir archivos o leer datos.
Ahora que ya tenemos configurada la conexión con nuestro Data Lake, el siguiente paso es disponer de un conjunto de datos que podamos cargar para realizar pruebas. En lugar de usar archivos reales, podemos generar datos sintéticos fácilmente con ayuda de las librerías Faker y Pandas.
El paquete Faker permite crear datos ficticios realistas (nombres, direcciones, fechas, correos electrónicos, etc.) en diferentes idiomas o culturas, lo que resulta ideal para pruebas de integración o desarrollo. Por su parte, Pandas nos servirá para estructurar esos datos en forma tabular y exportarlos luego en los formatos deseados.
En este ejemplo, vamos a generar 100.000 registros aleatorios que simulan las ventas de una tienda de informática. Cada registro incluirá información sobre la fecha de la venta, el producto, las unidades vendidas, el precio unitario, el total, el vendedor y la ciudad.
import pandas as pd
import random
from faker import Faker
from datetime import datetime, timedelta
# Configurar la localización de Faker
fake = Faker("es_ES")
# Definir el número de registros
n = 100_000
data = []
for _ in range(n):
fecha = fake.date_between(start_date='-30d', end_date='today')
producto = random.choice(["Laptop", "Smartphone", "Tablet", "Monitor", "Teclado", "Ratón"])
unidades = random.randint(1, 10)
precio_unitario = round(random.uniform(50, 1500), 2)
total = round(unidades * precio_unitario, 2)
vendedor = fake.name()
ciudad = fake.city()
data.append([fecha, producto, unidades, precio_unitario, total, vendedor, ciudad])
df = pd.DataFrame(data, columns=["fecha", "producto", "unidades", "precio_unitario", "total", "vendedor", "ciudad"])
df.head() fecha producto unidades precio_unitario total \
0 2025-11-05 Smartphone 9 189.39 1704.51
1 2025-11-22 Ratón 3 191.08 573.24
2 2025-11-30 Smartphone 10 1058.26 10582.60
3 2025-11-11 Ratón 4 1446.66 5786.64
4 2025-11-20 Ratón 4 1412.68 5650.72
vendedor ciudad
0 Alejo Amo Arteaga Ciudad
1 Constanza Corominas Pozuelo Pontevedra
2 Ramona Soto-Sáez Cuenca
3 Eduardo del Ferrer Ceuta
4 Rómulo Alarcón-Llabrés Tarragona
Al ejecutar este código, se generará un DataFrame de Pandas con 100.000 registros simulando ventas.
Consejo: La librería Faker incluye localizaciones para muchos idiomas (en_US, fr_FR, es_MX, etc.). Cambiar la localización permite que los nombres y ciudades de España sean más próximos a los esperados.
Ya disponemos de un DataFrame con datos simulados, así que el siguiente paso consiste en subirlo al Data Lake. No es necesario guardar el archivo temporalmente en disco; podemos escribirlo directamente en memoria y enviarlo al contenedor de Azure.
Para ello, utilizaremos un BytesIO como buffer intermedio, y construiremos un nombre de archivo organizado por año y mes (útil para estructurar el Data Lake siguiendo buenas prácticas de particionado temporal).
from io import BytesIO
from datetime import date
# Convertir el DataFrame a CSV en memoria
buffer = BytesIO()
df.to_csv(buffer, index=False)
buffer.seek(0)
# Crear nombre lógico del archivo con ruta año/mes automática
today = date.today()
year = today.strftime("%Y")
month = today.strftime("%m")
blob_name = f"{year}/{month}/ventas_demo_{today}.csv"
# Subir el CSV al contenedor RAW
blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob_name)
blob_client.upload_blob(buffer, overwrite=True)
print(f"Archivo CSV '{blob_name}' subido correctamente al contenedor '{container_name}'.") Este código genera automáticamente una carpeta por año y mes dentro del contenedor (raw/2025/11/), lo que facilita la organización y posterior procesamiento de los datos en pipelines o herramientas como Azure Synapse, Databricks o Data Factory.
El formato Parquet es ampliamente utilizado en entornos de Big Data porque almacena la información en forma columnar, lo que reduce significativamente el tamaño de los archivos y mejora el rendimiento en operaciones analíticas.
Subir un archivo Parquet al Data Lake es tan sencillo como cambiar el método to_csv() por to_parquet():
# Convertir el DataFrame a Parquet en memoria
buffer = BytesIO()
df.to_parquet(buffer, index=False)
buffer.seek(0)
# Generar nombre lógico con la misma estructura temporal
blob_name_parquet = f"{year}/{month}/ventas_demo_{today}.parquet"
# Subir el archivo Parquet
blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob_name_parquet)
blob_client.upload_blob(buffer, overwrite=True)
print(f"Archivo Parquet '{blob_name_parquet}' subido correctamente al contenedor '{container_name}'.") De esta manera, tendrás en tu Data Lake los mismos datos disponibles en dos formatos:
Esta práctica es especialmente útil en entornos de Data Engineering, donde distintos sistemas pueden requerir formatos diferentes según el tipo de procesamiento o herramienta utilizada.
Una vez subidos los archivos, es una buena práctica verificar que ambos se encuentran correctamente almacenados en el contenedor del Data Lake. Esto también nos permitirá comparar el tamaño entre los formatos CSV y Parquet, lo que suele reflejar claramente la ventaja del formato columnar en términos de espacio.
Podemos listar todos los blobs del contenedor raw con el siguiente código:
print("Archivos disponibles en el contenedor:")
for blob in container_client.list_blobs():
if blob.size == 0:
print(f" - {blob.name}")
else:
size_mb = blob.size / (1024 * 1024) # Convertir bytes a MB
print(f" - {blob.name} ({size_mb:.2f} MB)") Esto mostrará una salida similar a la siguiente:
Archivos disponibles en el contenedor:
- 2025
- 2025/11
- 2025/11/ventas_demo_2025-11-22.csv (6.39 MB)
- 2025/11/ventas_demo_2025-11-22.parquet (2.96 MB)
Como se puede observar, el archivo Parquet ocupa mucho menos espacio que el CSV, incluso cuando contienen exactamente los mismos datos. Esta diferencia es una de las principales razones por las que Parquet se ha convertido en el formato estándar para almacenamiento analítico en entornos de Big Data y Data Lakes modernos.
Consejo: En proyectos reales, este tipo de comprobación puede automatizarse dentro de un pipeline de carga o en scripts de validación, garantizando que los archivos se suben correctamente y cumplen con las políticas de particionado y almacenamiento.
Una vez que los archivos se han subido correctamente al Data Lake, es buena práctica comprobar que pueden leerse sin errores. De este modo confirmamos que el proceso de escritura y la configuración de acceso funcionan correctamente.
Podemos hacerlo fácilmente leyendo el mismo archivo que acabamos de subir:
# Leer el archivo CSV de vuelta desde Azure blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob_name) # Descargar el contenido del blob a un buffer en memoria stream = BytesIO() data = blob_client.download_blob() stream.write(data.readall()) stream.seek(0) # Cargarlo como DataFrame de pandas df_verificado = pd.read_csv(stream) df_verificado.head()
fecha producto unidades precio_unitario total \
0 2025-11-05 Smartphone 9 189.39 1704.51
1 2025-11-22 Ratón 3 191.08 573.24
2 2025-11-30 Smartphone 10 1058.26 10582.60
3 2025-11-11 Ratón 4 1446.66 5786.64
4 2025-11-20 Ratón 4 1412.68 5650.72
vendedor ciudad
0 Alejo Amo Arteaga Ciudad
1 Constanza Corominas Pozuelo Pontevedra
2 Ramona Soto-Sáez Cuenca
3 Eduardo del Ferrer Ceuta
4 Rómulo Alarcón-Llabrés Tarragona
Si todo ha ido bien, deberías ver en pantalla las primeras filas del DataFrame original, lo que confirma que la carga al Data Lake fue exitosa
Nota: Este tipo de verificación es útil en entornos de desarrollo o pruebas, pero no se recomienda hacerlo en producción. En sistemas reales, la comprobación de integridad debería realizarse mediante checksums, logs de control o procesos de auditoría de datos, no descargando los archivos completos.
En entornos de producción no es recomendable descargar los archivos para comprobar si se han cargado correctamente. Una alternativa más eficiente y segura es verificar su integridad comparando un hash o checksum calculado localmente antes de subirlo con el hash del archivo almacenado en Azure.
Esto permite asegurarse de que el archivo no se ha corrompido durante la transferencia.
Inicialmente, podemos generar un hash MD5 o SHA256 del contenido del archivo directamente desde el buffer antes de subirlo. Por ejemplo, usando hashlib:
import hashlib
# Calcular el hash del CSV antes de subirlo
buffer.seek(0)
hash_local = hashlib.md5(buffer.read()).hexdigest()
print("Hash local:", hash_local)
# Volvemos el buffer al inicio antes de subirlo
buffer.seek(0)
# Subir el blob (como antes)
blob_client.upload_blob(buffer, overwrite=True) Hash local: a2711dd21fce6a7b3baa666cf0b7913e
Azure Blob Storage genera automáticamente un MD5 hash de cada blob subido, disponible en sus propiedades. Podemos acceder a él fácilmente:
# Obtener propiedades del blob
props = blob_client.get_blob_properties()
# Azure almacena el MD5 en formato base64
import base64
hash_azure = base64.b64encode(props.content_settings.content_md5).decode()
print("Hash en Azure (base64):", hash_azure) Hash en Azure (base64): onEd0h/Oans7qmZs8LeRPg==
El único problema, es que en Azure el hash se tiene en base 64, así que para solo hay que transformar la base para comparar los hashes. Para verificar la integridad se puede hacer con:
# Convertir el hash local a base64 para compararlo
hash_local_base64 = base64.b64encode(bytes.fromhex(hash_local)).decode()
if hash_local_base64 == hash_azure:
print("El archivo se ha cargado correctamente (hash coincidente).")
else:
print("El archivo podría haberse modificado o corrompido durante la carga.") El archivo se ha cargado correctamente (hash coincidente).
Consejo: Usar checksums es una práctica recomendada en pipelines de datos críticos, ya que permite detectar errores silenciosos durante la carga o transferencia de grandes volúmenes de información.
En este tutorial hemos recorrido todos los pasos necesarios para cargar datos desde Python a un Data Lake en Azure de forma segura y automatizada.
Entre los puntos más importantes que hemos visto se incluyen:
azure-storage-blob, pandas, pyarrow y faker para generar y manejar datos de prueba.Faker y pandas.raw), nombres de archivos coherentes, separación por formatos y particionamiento temporal, todo pensado para facilitar pipelines futuros y analítica eficiente.Con estos pasos y buenas prácticas, tu Data Lake en Azure estará listo para recibir datos de cualquier origen y servir como base sólida para análisis, visualización o modelos de Machine Learning.
Nota: La imagen de este artículo fue generada utilizando un modelo de inteligencia artificial.
“El interés compuesto es la octava maravilla del mundo. El que lo entiende lo gana…
Tienes los datos de ventas de tres productos en dos años distintos y quieres saber…
Imagina la situación. Tu equipo lleva tres años con un modelo en producción. No es…
Cuando un banco evalúa una solicitud de crédito necesita responder a una pregunta aparentemente simple:…
En el octavo aniversario de Analytics Lane seguimos ampliando nuestro laboratorio de aplicaciones interactivas y,…
Hoy, 2 de mayo de 2026, Analytics Lane cumple exactamente ocho años. Todo empezó con…
This website uses cookies.