6a1520f458
Pipeline render_automatic_eda_folder: apunta el AutomaticEDA a una CARPETA de archivos tabulares (CSV/Parquet/JSON) o a una DuckDB existente y emite el informe de la BASE por capitulos en PDF (A5 movil) + PPTX (16:9) + Markdown. Documento-base con portada-base, resumen de todas las tablas y relaciones inter-tabla (FK candidatas por containment + diagrama Mermaid del join graph). Flag per_table_eda anexa el mini-EDA de cada tabla. Aditivo: render_automatic_eda (tabla unica) intacto. Funcion nueva load_folder_to_duckdb (infra, grupo eda+duckdb): carga una carpeta a una DuckDB (temp si no se da path), CREATE TABLE por archivo con read_csv_auto/ read_parquet/read_json_auto. dict-no-throw. Compone profile_database + los 3 renderers del motor AutomaticEDA + build_document (per-tabla), sin reimplementar su logica. Tests: golden 3 CSV relacionados (FK orders.customer_id->customers.id detectada) + edges (carpeta vacia, 1 tabla, DuckDB existente, path inexistente). fn index sin error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.3 KiB
6.3 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 | |||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| load_folder_to_duckdb | function | py | infra | 1.0.0 | impure | def load_folder_to_duckdb(folder: str, db_path: str = None, pattern: str = '*.csv,*.parquet,*.json') -> dict | Escanea el primer nivel de una CARPETA buscando archivos tabulares (CSV/TSV/TXT, Parquet, JSON/NDJSON) y los carga como tablas en una base DuckDB usando los lectores nativos read_csv_auto/read_parquet/read_json_auto. Es la pieza de entrada del EDA a nivel de carpeta (grupo eda). Por cada archivo crea una tabla cuyo nombre se deriva del basename saneado a [0-9a-zA-Z_] en minusculas (prefijo t_ si empieza por digito, sufijos _2/_3 ante colisiones, tabla_<i> si queda vacio). El path se escapa (comilla simple '->'') antes de interpolarlo porque los lectores DuckDB no aceptan el path como parametro posicional. Glob NO recursivo: un glob.glob(os.path.join(folder, g)) por cada patron del CSV, dedup y ordenado. db_path=None genera una DuckDB temporal (mkstemp, se borra el placeholder vacio porque DuckDB rechaza un archivo de 0 bytes) y devuelve su ruta. Un fallo al cargar un archivo concreto no aborta el resto: se registra en errors y se continua. Devuelve siempre un dict sin lanzar (estilo del grupo duckdb): {status:'ok', db_path, tables, errors} en exito (carpeta sin archivos tabulares incluida, tables=[]) y {status:'error', error} cuando la carpeta no existe o falla algo global. Depende del paquete duckdb (1.5.2). |
|
false | error_py_core |
|
|
dict. En exito: {status:'ok', db_path:str (ruta DuckDB usada), tables:[{name:str, source_file:str, n_rows:int}], errors:[{name?:str, source_file:str, error:str}]}. La carpeta sin archivos tabulares es un exito con tables=[] y errors=[]. En error (sin lanzar): {status:'error', error:str}. | true |
|
python/functions/infra/load_folder_to_duckdb_test.py | python/functions/infra/load_folder_to_duckdb.py |
Ejemplo
import sys
sys.path.insert(0, "python/functions")
from infra.load_folder_to_duckdb import load_folder_to_duckdb
# Preparar una carpeta de demo con dos CSV.
import os
os.makedirs("/tmp/eda_folder_demo", exist_ok=True)
with open("/tmp/eda_folder_demo/ventas.csv", "w") as f:
f.write("id,total\n1,10.5\n2,20.0\n3,5.25\n")
with open("/tmp/eda_folder_demo/clientes.csv", "w") as f:
f.write("id,nombre\n1,ana\n2,luis\n")
# Cargar todos los tabulares de la carpeta a una DuckDB temporal.
res = load_folder_to_duckdb("/tmp/eda_folder_demo")
print(res["status"]) # ok
print(res["db_path"]) # /tmp/tmpXXXXXXXX.duckdb (temporal)
for t in res["tables"]:
print(t["name"], t["n_rows"]) # ventas 3 / clientes 2
# Persistir en una DuckDB concreta y limitar a CSV.
res2 = load_folder_to_duckdb(
"/tmp/eda_folder_demo",
db_path="/tmp/eda_folder_demo/folder.duckdb",
pattern="*.csv",
)
print(res2["tables"]) # [{'name': 'clientes', ...}, {'name': 'ventas', ...}]
Cuando usarla
Cuando tienes una carpeta de datos sueltos (un dump, un export, varios CSV/Parquet
descargados) y quieres analizarlos juntos con SQL sin montar la ingesta a mano,
archivo por archivo. Es el primer eslabon del EDA a nivel de carpeta (grupo eda):
deja una DuckDB con una tabla por archivo, lista para perfilar con
duckdb_table_schema_py_infra, consultar con duckdb_query_readonly_py_infra, o
correlacionar aguas abajo. Usala antes de cualquier paso de perfilado cuando la
unidad de trabajo es "todos los archivos de este directorio".
Gotchas
- Glob NO recursivo: solo se escanea el primer nivel de
folder. Archivos en subdirectorios se ignoran (ni siquiera con**en el patron, porqueglob.globse llama sinrecursive=True). Si necesitas recursion, aplana la carpeta antes o amplia la funcion. - Saneo de nombres de tabla: el basename se reduce a
[0-9a-zA-Z_]en minusculas.Ventas 2024.csv-> tablaventas_2024. Dos archivos distintos pueden sanear al mismo nombre (a-b.csvya_b.csv); el segundo se desambigua con sufijo_2,_3, ... El mapeo real archivo->tabla esta entables[].name/tables[].source_file, no lo asumas. read_json_autorequiere JSON tabular (array de objetos u objetos NDJSON homogeneos). Un JSON anidado o irregular puede fallar la carga de ESA tabla; el error se registra enerrorsy el resto de archivos siguen cargandose.- Extension desconocida = se salta, no falla: queda anotada en
errorsconunsupported extension. Mapeo de lectores:.csv/.tsv/.txt->read_csv_auto,.parquet/.pq->read_parquet,.json/.ndjson->read_json_auto. - Escritura real en disco (impura). DuckDB es single-writer: si otro proceso
tiene
db_pathabierto en escritura,connectfalla con error de lock devuelto en el dict. Undb_pathcon un directorio padre inexistente tambien falla. db_path=Nonecrea un archivo temporal que NO se borra solo: la ruta se devuelve endb_pathpara que el llamador la consuma y la limpie cuando termine.- Tipos inferidos por los lectores
_auto: los tipos de columna los infiere DuckDB. Revisa el schema conduckdb_table_schema_py_infrasi el tipado importa aguas abajo.