COMUNICA MEDIANTE API TU APP WEB PYTHON Y GOOGLE SHEETS PARA AUTOMATIZACIONES O CONSULTA LIGERAS

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:

Pipeline
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

  1. Accede a Google Cloud Console: https://console.cloud.google.com
  2. Abre el selector de proyectos en la barra superior.
  3. Haz clic en Nuevo proyecto.
  4. Define un nombre para tu proyecto, por ejemplo: python-google-sheets-app.
  5. Crea el proyecto y selecciónalo.

Habilitar APIs necesarias

Dentro del proyecto:

  1. Ve a APIs y servicios luego a Biblioteca.
  2. Busca y habilita Google Sheets API.
  3. Busca y habilita Google Drive API.

Crear una cuenta de servicio

  1. Ve a APIs y servicios luego a Credenciales.
  2. Selecciona Crear credenciales luego Cuenta de servicio.
  3. Coloca un nombre, por ejemplo: google-sheets-reader.
  4. Coloca un rol, por ejemplo: Viewer para solo lectura o Editor si escribirás datos.
  5. Finaliza la creación.

Generar y descargar credenciales JSON

  1. Entra a la cuenta de servicio creada.
  2. Ve a Claves, Agregar clave y Crear nueva clave.
  3. Selecciona el formato JSON.
  4. Descarga el archivo y colócalo en tu proyecto, puede ser dentro de una carpeta credentials/.
Estructura sugerida del proyecto
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:

JSON
{
  "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:

.gitignore
credentials/
*.json

Configurar permisos en Google Sheets

  1. Abre el Google Sheets que consumirá tu app.
  2. Presiona Compartir.
  3. Agrega el correo de la cuenta de servicio, debe ser algo como: google-sheets-reader@python-google-sheets-app.iam.gserviceaccount.com .
  4. 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

  1. Registrar cada Google Sheet (url, worksheet, credenciales) en un diccionario.
  2. Leer datos crudos con un lector genérico y devolver un DataFrame.
  3. Si es el caso, aplicar limpieza de datos en una capa separada.
  4. 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.

Python — google_sheets_registry.py
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

Terminal
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:

Python — google_sheets_reader.py
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:

Python - data_cleaning.py
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