Files
fn_registry/python/functions/infra/excel_to_duckdb.md
T
egutierrez 927437a8d8 feat(infra): grupo claude-fleet — FleetView TUI + orquestacion de Claudes
Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una
sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI:

- list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals +
  runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId.
- list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables.
- wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console
  (preserva ancho del sidebar), tmux_map_claude_panes.
- launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r,
  mouse on, remain-on-exit off; fija el ancho del sidebar con hooks.
- docs/capabilities/claude-fleet.md + entrada en el INDEX.

Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes
varios de docs e infra de otra sesion, agrupados aqui para no perderlos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:04:41 +02:00

5.8 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
excel_to_duckdb function py infra 1.0.0 impure def excel_to_duckdb(xlsx_path: str, duckdb_path: str, table: str, sheet: str = None, mode: str = 'replace') -> dict Ingesta una hoja de un archivo .xlsx a una tabla DuckDB usando la extension nativa excel de DuckDB (camino activo, verificado en DuckDB 1.5.2). Abre el DuckDB destino en modo read-write (crea el archivo si no existe), carga la extension excel (INSTALL excel; LOAD excel;) y materializa la hoja con read_xlsx. El path del .xlsx y el nombre de la hoja se pasan como parametros posicionales (marcador ?) a read_xlsx, evitando inyeccion por esa via; el identificador de tabla destino se valida contra ^[A-Za-z_][A-Za-z0-9_]*$ y se cita. mode='replace' (default) hace CREATE OR REPLACE TABLE AS SELECT; mode='append' crea la tabla si no existe y luego INSERT INTO ... SELECT. Devuelve un dict sin lanzar (estilo del grupo duckdb): {status:'ok', table, row_count} en exito y {status:'error', error} en fallo. Depende de los paquetes duckdb (1.5.2) y, indirectamente, de la extension excel de DuckDB.
duckdb
excel
xlsx
ingest
etl
false error_py_core
re
duckdb
name desc
xlsx_path ruta al archivo .xlsx de origen. Debe existir y ser legible. Se pasa como parametro posicional a read_xlsx (no se interpola en el SQL).
name desc
duckdb_path ruta al archivo DuckDB destino. Se abre en modo escritura, que crea el archivo si no existe. DuckDB es single-writer: si otro proceso lo tiene abierto en escritura falla con error de lock.
name desc
table nombre de la tabla destino. Se valida contra ^[A-Za-z_][A-Za-z0-9_]*$ antes de interpolarlo (CREATE/INSERT no admiten parametro para el nombre de tabla). Identificador invalido devuelve {status:'error'} sin tocar la base.
name desc
sheet nombre de la hoja a leer. None (default) lee la primera hoja del libro. Se pasa como parametro posicional sheet=? a read_xlsx.
name desc
mode 'replace' (default) reemplaza la tabla entera con CREATE OR REPLACE TABLE AS SELECT; 'append' crea la tabla si no existe y luego inserta las filas con INSERT INTO ... SELECT. Otro valor devuelve {status:'error'}.
dict. En exito: {status:'ok', table:str, row_count:int} donde row_count es el numero de filas que tiene la tabla tras la ingesta. En error (sin lanzar): {status:'error', error:str}. true
test_replace_ingesta_primera_hoja
test_seleccion_de_hoja_por_nombre
test_append_acumula_filas
test_replace_reemplaza_no_acumula
test_identificador_invalido_devuelve_status_error
test_mode_invalido_devuelve_status_error
test_xlsx_inexistente_devuelve_status_error
python/functions/infra/excel_to_duckdb_test.py python/functions/infra/excel_to_duckdb.py

Ejemplo

import sys
sys.path.insert(0, "python/functions")
from infra.excel_to_duckdb import excel_to_duckdb

# Ingesta la primera hoja de un .xlsx a la tabla `ventas`, reemplazandola.
res = excel_to_duckdb(
    "/tmp/informe_mensual.xlsx",
    "/tmp/almacen.duckdb",
    "ventas",
    mode="replace",
)
print(res)   # {'status': 'ok', 'table': 'ventas', 'row_count': 1280}

# Ingesta una hoja concreta por nombre en modo append.
res2 = excel_to_duckdb(
    "/tmp/informe_mensual.xlsx",
    "/tmp/almacen.duckdb",
    "detalle",
    sheet="Detalle",
    mode="append",
)
print(res2)  # {'status': 'ok', 'table': 'detalle', 'row_count': 4096}

Cuando usarla

Cuando recibes datos en Excel (informes, exports, planillas manuales) y necesitas analizarlos o servirlos con SQL: es el primer eslabon del flujo Excel -> DuckDB -> PostgreSQL. Tras ingestar con esta funcion, usa duckdb_query_readonly_py_infra para analizar, duckdb_table_schema_py_infra para inspeccionar el schema inferido, y duckdb_to_postgres_py_pipelines para volcar a PostgreSQL y que Metabase/Grafana lo lean. mode='replace' para snapshots completos (refresco diario), mode='append' para acumular hojas sucesivas en una misma tabla.

Gotchas

  • Camino activo: extension nativa excel de DuckDB (verificado en DuckDB 1.5.2: read_xlsx lee .xlsx y acepta sheet=). NO se usa el fallback openpyxl. Si en algun entorno la extension fallara, habria que reactivar un fallback openpyxl (no presente hoy) — documentar el cambio aqui si ocurre.
  • INSTALL excel necesita red la primera vez por conexion: descarga la extension del repositorio de extensiones de DuckDB. Una vez instalada queda cacheada en el home de DuckDB y LOAD excel funciona offline. En un entorno sin red y sin la extension cacheada, la ingesta falla con {status:'error', ...} (no se lanza).
  • Escritura real en disco (impura). DuckDB es single-writer: si otro proceso tiene duckdb_path abierto en escritura, connect falla con error de lock devuelto en el dict.
  • A diferencia de read_only, este modo crea el archivo DuckDB si no existe. Un duckdb_path con un directorio padre inexistente si falla y se reporta como error.
  • Inferencia de tipos del .xlsx: read_xlsx infiere los tipos de columna. Los numeros suelen inferirse como DOUBLE (incluso enteros), las fechas pueden quedar como VARCHAR segun el formato de la celda. Revisa el schema resultante con duckdb_table_schema_py_infra si el tipado importa aguas abajo.
  • En mode='append' el schema lo fija la primera ingesta (CREATE TABLE IF NOT EXISTS). Si una hoja posterior tiene columnas distintas, el INSERT puede fallar por desajuste de columnas; el error se devuelve en el dict.
  • El identificador table se valida (las CREATE/INSERT no parametrizan el nombre de tabla). Un nombre con caracteres fuera de [A-Za-z0-9_] devuelve {status:'error', error:'invalid table identifier'} sin tocar la base.