Conectar a una app web desarrollada en Python con Google Sheets usando su API
Introducción
En aplicaciones web desarrolladas en Python surge la necesidad de consultar datos que cambian constantemente y para lograrlo, lo menos óptimo es subir constantemente archivos al servidor donde vive la app.
Google Sheets combinado con su API, ofrece una solución práctica, permite que usuarios no necesariamente técnicos actualicen datos desde una hoja de cálculo en línea, mientras la app web consulta esos datos de forma constante o bajo demanda.
En esta publicación te muestro una forma de responder a las siguientes preguntas:
- ¿Cómo configurar correctamente Google Cloud y la Google Sheets API?
- ¿Cómo diseñar una arquitectura modular y escalable en Python?
- ¿Cómo leer múltiples Google Sheets desde una app web?
- ¿Cómo evitar errores comunes y proteger credenciale?.
¿Por qué usar Google Sheets como fuente de datos?
Google Sheets puede funcionar como una fuente de datos ligera cuando necesitas un punto de actualización sencillo para stakeholders del negocio, eso ofrece ventajas como:
- Interfaz familiar para equipos no técnicos.
- Actualización inmediata sin tocar código.
- Control de permisos por usuario y por recurso.
- Historial de cambios y recuperación de versiones.
- Integración nativa con Google Cloud y APIs.
Y los casos de uso comunes pueden ser:
- Dashboards de ventas o KPIs.
- Datos históricos y forecasting.
- Control de metas, presupuestos, consumos y planeación.
Arquitectura general propuesta
El objetivo es separar responsabilidades y desacoplar la lectura de datos del resto de la app:
Google Sheets -> Hoja de cálculo en línea
│
▼
Google Sheets API
│
▼
google_sheets_registry.py -> Diccionario que centraliza datos esenciales de casa Sheets
│
▼
google_sheets_reader.py -> Lectura genérica
│
▼
data_cleaning.py -> Limpieza de datos si es necesaria
│
▼
callbacks, layouts, forecasting... -> Uso de datos para lograr el objetivo
Parte I. Configuración de Google Sheets API en Google Cloud
Crear un proyecto en Google Cloud
- Accede a Google Cloud Console:
https://console.cloud.google.com - Abre el selector de proyectos en la barra superior.
- Haz clic en Nuevo proyecto.
- Define un nombre para tu proyecto, por ejemplo:
python-google-sheets-app. - Crea el proyecto y selecciónalo.
Habilitar APIs necesarias
Dentro del proyecto:
- Ve a APIs y servicios luego a Biblioteca.
- Busca y habilita Google Sheets API.
- Busca y habilita Google Drive API.
Crear una cuenta de servicio
- Ve a APIs y servicios luego a Credenciales.
- Selecciona Crear credenciales luego Cuenta de servicio.
- Coloca un nombre, por ejemplo:
google-sheets-reader. - Coloca un rol, por ejemplo: Viewer para solo lectura o Editor si escribirás datos.
- Finaliza la creación.
Generar y descargar credenciales JSON
- Entra a la cuenta de servicio creada.
- Ve a Claves, Agregar clave y Crear nueva clave.
- Selecciona el formato JSON.
- Descarga el archivo y colócalo en tu proyecto, puede ser dentro de una carpeta
credentials/.
project/
├── app/
├── utils/
│ └── google_sheets_registry.py
│ └── google_sheets_reader.py
│ └── data_cleaning.py
├── credentials/
│ └── google_sheets_service.json
├── .gitignore
├── requeriments.txt
├── README.md
El JSON será algo como:
{
"type": "service_account",
"project_id": "google-sheets-reader",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\...",
"client_email": "google-sheets-reader@python-google-sheets-app.iam.gserviceaccount.com ",
"client_id": "números...",
"auth_uri": "https://...",
"token_uri": "https://...",
"auth_provider_x509_cert_url": "https://www.googleapis.com/...",
"client_x509_cert_url": "https://www.googleapis.com/...",
"universe_domain": "googleapis.com"
}
Proteger credenciales
Agrega al archivo .gitignore:
credentials/
*.json
Configurar permisos en Google Sheets
- Abre el Google Sheets que consumirá tu app.
- Presiona Compartir.
- Agrega el correo de la cuenta de servicio, debe ser algo como:
google-sheets-reader@python-google-sheets-app.iam.gserviceaccount.com. - Asigna permisos, por ejemplo: Lector si solo leerás, Editor si escribirás.
Verificación final de acceso
Antes de implementar código, asegúrate de que estos puntos están correctos:
- APIs habilitadas: Sheets API y Drive API.
- Archivo JSON válido y ubicado en la ruta esperada.
- La cuenta de servicio tiene acceso al Google Sheet, está compartido explícitamente.
- El nombre del worksheet (hoja específica del sheets) existe y coincide exactamente (case-sensitive).
Parte II. Diseño de una arquitectura modular en Python
Principios de diseño
- No hardcodear URLs ni credenciales dentro de funciones de lectura.
- Centralizar configuración en un registro único (single source of truth).
- Reutilizar un lector genérico para cualquier Sheet.
- Separar lectura (raw) de limpieza y tipado (clean).
- Facilitar agregar nuevos Sheets sin cambiar la lógica del lector, es decir, que las funciones de lectura sean totalembte reutilizables.
Flujo completo de datos
- Registrar cada Google Sheet (url, worksheet, credenciales) en un diccionario.
- Leer datos crudos con un lector genérico y devolver un DataFrame.
- Si es el caso, aplicar limpieza de datos en una capa separada.
- Consumir el DataFrame limpio en los diversos procesos según el objetivo de negocio.
Registro centralizado de Google Sheets
Esta propuesta de archivo funciona como un diccionario de configuración global y su objetivo es concentrar los datos más esenciales para identificar cada Sheets y replicando la misma estructura cada se agrega uno nuevo sin necesidad de cambiar lógica, los daots serán: URL del Sheet, nombre de worksheet (hoja específica del sheets) y ruta de las credenciales.
import os
"""
Registro central de Google Sheets disponibles en la app.
Cada entrada define:
- url: enlace del Google Sheets.
- worksheet: nombre del worksheet dentro del archivo.
- credentials: ruta local al JSON de la cuenta de servicio.
"""
GOOGLE_SHEETS_REGISTRY = {
"nombre_para_identificar_sheets_1": {
"url": "https://docs.google.com/spreadsheets/d/...",
"worksheet": "Hoja_1",
"credentials": os.path.join("credentials", "google_sheets_service.json"),
},
"nombre_para_identificar_sheets_2": {
"url": "https://docs.google.com/spreadsheets/d/...",
"worksheet": "Hoja_2",
"credentials": os.path.join("credentials", "google_sheets_service.json"),
},
...
}
Lector genérico de Google Sheets
Este módulo encapsula toda la lógica de autenticación y lectura. Recibe una sheet_key
(la llave del diccionario en google_sheets_registry.py) y devuelve un DataFrame.
Instalación de dependencias
Con tu entorno virtual activo, instala al menos las siguientes dependencias
pip install gspread google-auth pandas pyarrow
Código del lector
La propuesta de código es la siguinete e incluye comentarios en cada bloque o línea para entender qué hace cada parte:
import pandas as pd
import gspread
from typing import List # Tipado
from google.oauth2.service_account import Credentials
from utils.google_sheets_registry import GOOGLE_SHEETS_REGISTRY
"""
Autentica contra Google, lee un worksheet, lo devuelve como DataFrame
y se incluye un fallback a disco por si falla la API.
Diseño general:
1) Obtener credenciales y scopes
2) Construir cliente autenticado (gspread)
3) Abrir el Sheet por URL
4) Seleccionar worksheet por nombre
5) Obtener valores y convertir a DataFrame
6) Guardar un fallback local para tolerancia a fallos
"""
# Scopes necesarios para acceso de solo lectura a Sheets y Drive
GOOGLE_SCOPES = [
"https://www.googleapis.com/auth/spreadsheets.readonly",
"https://www.googleapis.com/auth/drive.readonly",
]
# Ruta de fallback por si falla la lectura de la API
FALLBACK_PARQUET_PATH = "/tmp/gsheets_fallback.parquet"
def get_gspread_client(credentials_path: str) -> gspread.Client:
"""
Crea un cliente autenticado de gspread usando el JSON indicado.
- credentials_path: ruta al archivo JSON de la cuenta de servicio.
- scopes: permisos autorizados (en este caso, solo lectura).
"""
creds = Credentials.from_service_account_file(
credentials_path, # Ruta al JSON de credenciales
scopes=GOOGLE_SCOPES, # Scopes necesarios
)
return gspread.authorize(creds) # Autoriza y devuelve cliente
def values_to_dataframe(values: List[List[str]]) -> pd.DataFrame:
"""
Convierte la matriz de valores del worksheet a un DataFrame.
- values[0]: encabezados
- values[1:]: filas
"""
if not values:
return pd.DataFrame()
headers = values[0] # Primera fila como encabezados
rows = values[1:] if len(values) > 1 else [] # Resto como filas
return pd.DataFrame(rows, columns=headers) # Crea DataFrame
def read_sheet_to_df(sheet_key: str, use_fallback: bool = True) -> pd.DataFrame:
"""
Lee una hoja de Google Sheets registrada en el registry y devuelve un DataFrame.
Parámetros:
- sheet_key: llave del diccionario GOOGLE_SHEETS_REGISTRY.
- use_fallback: si True, intenta leer desde disco si falla la API.
Flujo:
1) Validar sheet_key
2) Leer configuración (url, worksheet, credentials)
3) Autenticar y obtener valores
4) Convertir a DataFrame
5) Guardar fallback
6) Si falla, intentar leer fallback (si use_fallback=True)
"""
if sheet_key not in GOOGLE_SHEETS_REGISTRY:
raise ValueError(f"'{sheet_key}' no está registrado en GOOGLE_SHEETS_REGISTRY")
sheet_info = GOOGLE_SHEETS_REGISTRY[sheet_key] # Obtiene info de conexión
url = sheet_info["url"] # URL del Sheets
worksheet_name = sheet_info["worksheet"] # Nombre del worksheet
credentials_path = sheet_info["credentials"] # Ruta al JSON de credenciales
try:
# 1) Autentica y crea cliente
client = get_gspread_client(credentials_path)
# 2) Abre el Sheets por URL
sheet = client.open_by_url(url)
# 3) Selecciona el worksheet por nombre
worksheet = sheet.worksheet(worksheet_name)
# 4) Obtiene todos los valores (incluye encabezado)
values = worksheet.get_all_values()
# 5) Convierte a DataFrame
df = values_to_dataframe(values)
# 6) Guardar fallback para tolerancia a fallos
try:
df.to_parquet(FALLBACK_PARQUET_PATH, index=False)
except Exception:
# Si falla el guardado del fallback, no detiene la app.
pass
return df
except Exception as e:
# Si la API falla, intenta fallback si está habilitado
if use_fallback:
try:
return pd.read_parquet(FALLBACK_PARQUET_PATH)
except Exception:
raise RuntimeError(f"Falló la API y también el fallback: {e}")
else:
# Si no hay fallback, propaga error original
raise e
Uso desde una app web
Una vez que el registry y el reader existen, el uso se vuelve directo y muy sencillo, por ejemplo, en el archivo donde podrías elaborar la limpieza de tus datos lo consigues de la siguiente forma:
from utils.google_sheets_reader import read_sheet_to_df
df_sales = read_sheet_to_df("nombre_para_identificar_sheets_1")
En una app Dash, este DataFrame puede consumirse en callbacks que alimentan una tabla o construyan una gráfica. En Flask, puede alimentar endpoints o procesos internos que renderizan templates.
Errores comunes y cómo evitarlos
- No compartir el Sheet con la cuenta de servicio, esto es el error más común.
- Usar un nombre incorrecto del worksheet (case-sensitive: sensible a mayúsculas y minúsculas).
- Ruta incorrecta al JSON.
- Subir el JSON a GitHub accidentalmente.
- Realizar demasiadas lecturas sin cache puede tener un alto impacto en performance y cuotas con Google.
- No manejar caídas temporales de la API, usa fallback o reintentos.
Tips de rendimiento y seguridad
-
Implementa caching: memoria (
@lru_cache(maxsize=N)), Redis o una capa de persistencia. - Usa fallback local si tu app debe seguir funcionando ante fallas externas.
- Limita permisos al mínimo con scopes de solo lectura si aplica.
- Evita exponer credenciales en repositorios o logs.
- Considera un refresco controlado: por ejemplo, cada 5 o 15 minutos en lugar de por request salvo que sea realmente necesario.
Conclusión
Integrar Google Sheets a una app web en Python puede ser una solución eficiente cuando requieres un punto de actualización simple para usuarios no técnicos. Con una arquitectura modular, escalabre y reutilizable (registry + reader + cleaning), permitiendo aumentar el número de fuentes, aislar credenciales y mantener un código fácil de extender.
La clave para producción es controlar lecturas (caching), asegurar credenciales y manejar fallas externas con estrategias como fallback o refresh por intervalos.
Bibliografía y recursos recomendados
- Google Sheets API Documentation:
https://developers.google.com/sheets/api - Google Cloud Service Accounts:
https://cloud.google.com/iam/docs/service-accounts - gspread Documentation:
https://docs.gspread.org/