Jupyter Notebook no Seu Data Lake em 60 Segundos
Você quer explorar seu data lake em um notebook Jupyter. Aqui está o que normalmente parece:
- Instalar JupyterLab
- Instalar DuckDB e os bindings Python
- Descobrir qual bucket S3 tem seus dados
- Instalar boto3 e configurar credenciais AWS
- Escrever o boilerplate de configuração S3 do DuckDB
- Descobrir manualmente quais tabelas existem
- Escrever as instruções de leitura de Parquet para cada tabela
- Torcer para acertar os caminhos
São 20 minutos de setup antes de escrever uma única query analítica. Toda vez.
O Jeito DataSpoc Lens
dataspoc-lens add-bucket company s3://company-data-lakedataspoc-lens notebookPronto. O JupyterLab abre no seu navegador com cada tabela no seu data lake já montada como uma view DuckDB. SQL magic funciona direto. A variável conn está pronta para pandas.
O Que Acontece Por Baixo
Quando você executa dataspoc-lens notebook, o Lens:
- Lê o manifesto de
s3://company-data-lake/.dataspoc/manifest.json - Cria uma conexão DuckDB com credenciais S3 do seu ambiente
- Monta cada caminho Parquet como uma view nomeada
- Gera um script de inicialização (
~/.dataspoc/jupyter_startup.py) - Inicia o JupyterLab com o script de inicialização pré-carregado
O script de inicialização é assim (auto-gerado, você nunca o edita):
# ~/.dataspoc/jupyter_startup.py (auto-generated)import duckdb
conn = duckdb.connect()
# S3 configuration (from environment)conn.execute("INSTALL httpfs; LOAD httpfs;")conn.execute("SET s3_region = 'us-east-1';")
# Mount all tables from manifestconn.execute(""" CREATE VIEW raw__postgres__orders AS SELECT * FROM read_parquet('s3://company-data-lake/raw/postgres/orders/*.parquet')""")conn.execute(""" CREATE VIEW raw__postgres__customers AS SELECT * FROM read_parquet('s3://company-data-lake/raw/postgres/customers/*.parquet')""")conn.execute(""" CREATE VIEW curated__sales__customers AS SELECT * FROM read_parquet('s3://company-data-lake/curated/sales/customers/*.parquet')""")# ... one view per table in your lake
print(f"DataSpoc Lens: {len(conn.execute('SHOW TABLES').fetchall())} tables mounted")print("Use 'conn' for queries or %%sql magic for inline SQL")Exemplos de Células do Notebook
Célula 1: Ver O Que Está Disponível
# All your tables are already hereconn.sql("SHOW TABLES").show()┌─────────────────────────────────────┐│ name │├─────────────────────────────────────┤│ raw__postgres__orders ││ raw__postgres__customers ││ raw__postgres__order_items ││ curated__sales__customers ││ raw__google_sheets__campaigns │└─────────────────────────────────────┘Célula 2: SQL Magic
%%sqlSELECT DATE_TRUNC('month', created_at) as month, COUNT(*) as orders, SUM(amount) as revenueFROM raw__postgres__ordersWHERE created_at >= '2026-01-01'GROUP BY monthORDER BY month┌────────────┬────────┬───────────┐│ month │ orders │ revenue │├────────────┼────────┼───────────┤│ 2026-01-01 │ 3,421 │ 284,500 ││ 2026-02-01 │ 3,892 │ 312,100 ││ 2026-03-01 │ 4,156 │ 341,800 ││ 2026-04-01 │ 2,847 │ 228,400 │└────────────┴────────┴───────────┘Célula 3: Pandas DataFrame
df = conn.sql(""" SELECT customer_id, COUNT(*) as order_count, SUM(amount) as total_spend, MAX(created_at) as last_order FROM raw__postgres__orders GROUP BY customer_id""").df()
df.describe() order_count total_spendcount 3201.000000 3201.000000mean 14.340000 832.450000std 8.230000 456.780000min 1.000000 12.990000max 89.000000 8945.000000Célula 4: Gráfico Matplotlib
import matplotlib.pyplot as plt
monthly = conn.sql(""" SELECT DATE_TRUNC('month', created_at) as month, SUM(amount) as revenue FROM raw__postgres__orders WHERE created_at >= '2025-01-01' GROUP BY month ORDER BY month""").df()
plt.figure(figsize=(12, 5))plt.bar(monthly["month"].dt.strftime("%b %Y"), monthly["revenue"])plt.title("Monthly Revenue")plt.ylabel("Revenue ($)")plt.xticks(rotation=45)plt.tight_layout()plt.show()Célula 5: JOIN de Múltiplas Fontes
%%sqlSELECT c.channel, COUNT(DISTINCT o.customer_id) as customers, SUM(o.amount) as revenue, ROUND(SUM(o.amount) / COUNT(DISTINCT o.customer_id), 2) as avg_revenue_per_customerFROM raw__postgres__orders oJOIN raw__postgres__customers cu ON o.customer_id = cu.idJOIN raw__google_sheets__campaigns c ON cu.utm_source = c.channelGROUP BY c.channelORDER BY revenue DESCA Alternativa Marimo
Prefere notebooks reativos? O Lens também suporta Marimo:
dataspoc-lens notebook --runtime marimoIsso inicia um notebook Marimo com as mesmas tabelas pré-montadas:
import marimo as moimport duckdb
# conn is pre-configured (same startup script)conn = duckdb.connect()# ... tables already mounted
# Marimo's built-in SQL supportresult = mo.sql(""" SELECT channel, SUM(amount) as revenue FROM raw__postgres__orders GROUP BY channel""", connection=conn)
# Reactive: change the query, chart updates automaticallymo.ui.table(result)Vantagens do Marimo:
- Execução reativa (células re-executam quando dependências mudam)
- Widgets de UI integrados (sliders, dropdowns)
- Reprodutível (sem estado oculto)
- Exporta para scripts Python
Demo Docker: Ambiente Autocontido Completo
Quer experimentar sem instalar nada? Use a demo Docker:
docker run -it --rm \ -p 8888:8888 \ -e AWS_ACCESS_KEY_ID \ -e AWS_SECRET_ACCESS_KEY \ -e AWS_DEFAULT_REGION \ dataspoc/lens-notebook:latest \ --bucket s3://company-data-lakeIsso te dá:
- JupyterLab rodando em
http://localhost:8888 - DuckDB com todas as tabelas do seu bucket montadas
%%sqlmagic pré-configurado- pandas, matplotlib, seaborn, plotly pré-instalados
- Variável
connpronta para usar
Docker Compose para Uso em Time
version: "3.8"services: notebook: image: dataspoc/lens-notebook:latest ports: - "8888:8888" environment: - AWS_ACCESS_KEY_ID - AWS_SECRET_ACCESS_KEY - AWS_DEFAULT_REGION - DATASPOC_BUCKET=s3://company-data-lake volumes: - ./notebooks:/home/jovyan/notebooksdocker compose upCompartilhe o docker-compose.yaml com seu time. Todos recebem o mesmo ambiente, mesmas tabelas, mesmas views SQL. Sem problemas de “funciona na minha máquina”.
Dicas
Múltiplos buckets:
dataspoc-lens add-bucket sales s3://company-salesdataspoc-lens add-bucket marketing s3://company-marketingdataspoc-lens notebook# Both buckets' tables are mountedAtualizar tabelas sem reiniciar:
# In a notebook cellfrom dataspoc_lens import LensClientlens = LensClient()lens.refresh() # Re-reads manifest, mounts new tablesUsar com VS Code Jupyter:
dataspoc-lens notebook --no-browser --ip 0.0.0.0# Then connect VS Code to the running Jupyter serverO Resumo de 60 Segundos
| Passo | Comando | Tempo |
|---|---|---|
| Conectar bucket | dataspoc-lens add-bucket company s3://... | 2s |
| Iniciar notebook | dataspoc-lens notebook | 5s |
| Começar a consultar | %%sql SELECT ... | 0s (tabelas já estão lá) |
Sem boto3. Sem configuração de credenciais. Sem adivinhar caminhos Parquet. Sem boilerplate de setup DuckDB.
Apenas abra o notebook e escreva SQL.