Fluxo Técnico Modular para Preparação de Dados de Vendas
1. Contexto
Antes de iniciar qualquer análise, é importante garantir que os dados estejam organizados e disponíveis em um formato que permita leitura e validação. Este projeto foi estruturado como um pipeline em Python para tratar dados de vendas, com foco em etapas como ingestão, verificação e exportação. A proposta é facilitar o uso dos dados em relatórios e visualizações.
2. Objetivo
Apresentar um fluxo de trabalho em Python para organizar e validar dados de vendas. O projeto é dividido em módulos que tratam cada etapa separadamente. Os resultados são gerados em formatos como CSV, JSON e TXT, e podem ser utilizados por diferentes perfis de usuários.
3. Metodologia
O projeto foi dividido em módulos independentes, cada um com uma função específica. A execução é feita por um arquivo principal que chama os demais componentes. A seguir estão os módulos utilizados:
main.py: executa o pipeline completo;config.py: define os caminhos e parâmetros do projeto;utils.py: contém funções auxiliares como leitura de arquivos e configuração de logs;validators.py: aplica regras de estrutura e negócio aos dados;diagnostics.py: gera informações técnicas sobre os dados e o processo.
A sequência de execução segue as etapas de leitura, validação, diagnóstico e exportação.
4. Preparação do Projeto
Nesta etapa inicial o objetivo é garantir que o ambiente de execução do pipeline esteja corretamente configurado e que os artefatos básicos (entradas, diretórios de saída e logging) sejam criados de forma reprodutível e rastreável. A preparação aborda:
- Configuração do logging com rotação e saída no console;
- Criação dos diretórios necessários (
logseoutput); - Leitura segura do arquivo de entrada (
dados_vendas.csv) com validações de existência e encoding; - Aplicação das validações de estrutura e regras de negócio (módulo
validators.py); - Geração de diagnóstico técnico (módulo
diagnostics.py) e exportação dos metadados.
# ============================================================
# 4. Preparação do Projeto
# ============================================================
# Compatibilidade de anotações de tipos
from __future__ import annotations
# Bibliotecas padrão
import logging # Sistema de logging
from pathlib import Path # Manipulação de caminhos
from typing import Dict, Any # Tipagem de funções
import os # Operações de diretórios
import uuid # Identificadores únicos (usados em modais HTML)
import html # Escapar conteúdo de arquivos para exibição segura
# Bibliotecas externas
import pandas as pd # Manipulação de DataFrames
from IPython.display import display, HTML # Exibição em notebooks
# Imports do projeto
from config import ( # Configurações globais
INPUT_CSV,
LOGS_DIR,
OUTPUT_DIR,
META_JSON,
RELATORIO_TXT
)
from utils import ( # Funções auxiliares
setup_logging, # Configuração de logging
ensure_dirs, # Criação de diretórios
read_csv_safely, # Leitura segura de CSV
save_json, # Salvamento em JSON
save_dataframe, # Salvamento de DataFrame em CSV
moldura_texto # Impressão de moldura de seção
)
from validators import run_validations # Validações de estrutura e regras de negócio
from diagnostics import ( # Diagnóstico técnico
diagnostico_dados,
gerar_relatorio_texto
)
def preparar_ambiente(
input_csv: str = INPUT_CSV,
logs_dir: str = LOGS_DIR,
output_dir: str = OUTPUT_DIR,
) -> Dict[str, Any]:
"""
Etapa 4 - Preparação do Projeto.
- Configura logging (arquivo + console, com rotação)
- Cria diretórios necessários (logs, output, metadados, resumo)
- Lê o dataset CSV de vendas de forma segura
- Aplica validações de estrutura e regras de negócio
- Gera diagnóstico técnico e exporta metadados e relatório
"""
# Configuração do logger (arquivo pipeline.log + console) com nível INFO
logger = setup_logging(
logs_dir=logs_dir,
filename="pipeline.log",
level=logging.INFO
)
# Garantia de diretórios base e derivados usados na execução
ensure_dirs(
logs_dir,
output_dir,
Path(output_dir) / "metadados",
Path(output_dir) / "resumo"
)
# Registro do início da etapa
logger.info(">>> Iniciando etapa 4: Preparação do Projeto")
# 2) Leitura segura do dataset CSV (existência e encoding)
df = read_csv_safely(input_csv, logger=logger)
# 3) Validação e padronização das colunas e tipos
df = run_validations(df, logger=logger)
# 4) Diagnóstico técnico e metadados (shape, dtypes, nulos, conversões)
meta = diagnostico_dados(df, logger=logger)
# 5) Salvamento dos metadados (JSON) e relatório textual consolidado
try:
# Salva metadados em JSON no diretório de saída/metadados
save_json(meta, str(Path(output_dir) / "metadados" / Path(META_JSON).name))
# Gera relatório textual consolidado no diretório de logs
gerar_relatorio_texto(
meta=meta,
caminho=str(Path(logs_dir) / Path(RELATORIO_TXT).name),
logger=logger
)
# Registro de sucesso
logger.info("Metadados e relatório gerados com sucesso.")
except Exception as exc:
# Aviso em caso de falha ao salvar
logger.warning(f"Falha ao salvar metadados/relatório: {exc}")
# Registro de conclusão
logger.info(">>> Etapa 4 concluída com sucesso.")
# Retorno para etapas seguintes
return {"df": df, "meta": meta, "logger": logger}
# Execução local para validação
if __name__ == "__main__":
# Executa a preparação do ambiente e captura o resultado
resultado = preparar_ambiente()
# Extrai DataFrame e metadados do retorno para inspeção
df = resultado["df"]
meta = resultado["meta"]
# Cabeçalho da seção de preparação no console
moldura = "-" * 25
print(f"\n{moldura}>>> 4. Preparação do Projeto <<< {moldura}\n")
# Exibe dimensões do dataset (linhas e colunas) usando os metadados
print(f"Linhas: {meta['shape']['linhas']} | Colunas: {meta['shape']['colunas']}")
# Exibe status da conversão da coluna 'mes' para datetime, se aplicável
print(f"Conversão 'mes' para datetime: {meta.get('mes_convertido_para_datetime', False)}")
2024-11-16 15:25:34,175 | INFO | pipeline_dados | >>> Iniciando etapa 4: Preparação do Projeto
2024-11-16 15:25:34,183 | INFO | pipeline_dados | Arquivo CSV carregado com sucesso: dados_vendas.csv (linhas=500, colunas=7)
2024-11-16 15:25:34,185 | INFO | pipeline_dados | Estrutura validada: todas as colunas obrigatórias presentes.
2024-11-16 15:25:34,191 | INFO | pipeline_dados | Coluna 'mes' convertida para datetime64[ns].
2024-11-16 15:25:34,193 | INFO | pipeline_dados | Coluna 'vendedor_id' convertida para category.
2024-11-16 15:25:34,197 | INFO | pipeline_dados | Coluna 'produto_id' convertida para category.
2024-11-16 15:25:34,199 | INFO | pipeline_dados | Coluna 'quantidade' convertida para int64.
2024-11-16 15:25:34,201 | INFO | pipeline_dados | Coluna 'preco_unitario' convertida para float64.
2024-11-16 15:25:34,203 | INFO | pipeline_dados | Coluna 'desconto' convertida para float64.
2024-11-16 15:25:34,205 | INFO | pipeline_dados | Coluna 'valor_total' convertida para float64.
2024-11-16 15:25:34,207 | INFO | pipeline_dados | Dtypes após padronização: {'mes': 'datetime64[ns]', 'vendedor_id': 'category', 'produto_id': 'category', 'quantidade': 'int64', 'preco_unitario': 'float64', 'desconto': 'float64', 'valor_total': 'float64'}
2024-11-16 15:25:34,210 | INFO | pipeline_dados | Regras de negócio validadas sem inconsistências.
2024-11-16 15:25:34,212 | INFO | pipeline_dados | Executando diagnóstico dos dados...
2024-11-16 15:25:34,217 | INFO | pipeline_dados | Coluna 'mes' convertida para datetime com sucesso.
2024-11-16 15:25:34,219 | INFO | pipeline_dados | Gerando relatório textual consolidado...
2024-11-16 15:25:34,222 | INFO | pipeline_dados | Relatório textual salvo em logs\relatorio_pipeline.txt
2024-11-16 15:25:34,224 | INFO | pipeline_dados | Metadados e relatório gerados com sucesso.
2024-11-16 15:25:34,225 | INFO | pipeline_dados | >>> Etapa 4 concluída com sucesso.
------------------------->>> 4. Preparação do Projeto <<< ------------------------- Linhas: 500 | Colunas: 7 Conversão 'mes' para datetime: True
5. Metadados do Dataset e Visualização de Arquivos
Esta etapa tem como objetivo gerar e registrar os metadados técnicos do dataset de vendas processado. Esses metadados permitem documentar as principais características da base, como dimensões, tipos de dados e informações de integridade. A saída é exportada em formato CSV e JSON para o diretório de saída configurado no pipeline.
Disponibilizamos também um recurso opcional para leitura e exibição dos arquivos principais do projeto, permitindo visualizar o conteúdo de cada módulo (main.py, config.py, validators.py, diagnostics.py, utils.py).
- Exportação de metadados técnicos do dataset em CSV (
output/metadados/metadados.csv); - Salvamento de informações de diagnóstico em JSON (
output/pipeline_metadados.json); - Geração do relatório textual consolidado (
logs/relatorio_pipeline.txt); - Visualização opcional dos arquivos de código-fonte do pipeline diretamente no notebook.
# ============================================================
# 5. Metadados do Dataset e Visualização de Arquivos
# ============================================================
def gerar_metadados(df: pd.DataFrame, logger=None) -> pd.DataFrame:
"""
Etapa 5 - Metadados do Dataset e Visualização de Arquivos.
- Extrai metadados técnicos do dataset de vendas processado
- Cria DataFrame com colunas, descrições e tipos de dados
- Exporta os metadados em CSV no diretório de saída
- Exibe os metadados no notebook
Parâmetros:
df (pd.DataFrame): DataFrame de vendas validado.
logger (logging.Logger, opcional): Logger configurado do pipeline.
Retorno:
pd.DataFrame: DataFrame contendo metadados e descrições de variáveis.
"""
# Exibe título da etapa
moldura_texto("5. Metadados do Dataset")
# Diretório para exportação
meta_dir = os.path.join(OUTPUT_DIR, "metadados")
os.makedirs(meta_dir, exist_ok=True)
meta_csv_path = os.path.join(meta_dir, "metadados.csv")
# Extração dos metadados técnicos
meta = diagnostico_dados(df, logger)
# Dicionário com descrições das variáveis
descricao_variaveis = {
"mes": "Data da venda (mês/ano)",
"vendedor_id": "Identificação do vendedor",
"produto_id": "Identificação do produto",
"quantidade": "Quantidade vendida",
"preco_unitario": "Preço unitário do produto",
"desconto": "Percentual de desconto aplicado",
"valor_total": "Valor total da venda (após desconto)",
}
# Monta DataFrame com colunas, descrições e tipos
df_meta = pd.DataFrame({
"Coluna": list(meta["dtypes"].keys()),
"Descrição": [descricao_variaveis.get(c, "") for c in meta["dtypes"].keys()],
"Tipo de Dados": list(meta["dtypes"].values()),
})
# Exporta CSV e exibe resumo
save_dataframe(df_meta, meta_csv_path, index=False)
if logger:
logger.info(f"Metadados exportados para {meta_csv_path}")
display(df_meta)
return df_meta
def visualizar_arquivos_projeto():
"""
Exibe, no notebook, o conteúdo dos principais arquivos do pipeline.
Utiliza janelas modais simples em HTML, sem acionar downloads.
"""
# Exibe título da etapa
moldura_texto("Visualização dos Arquivos do Projeto")
# Função auxiliar para ler e escapar conteúdo de arquivos
def read_text(path: str) -> str:
with open(path, "r", encoding="utf-8") as f:
return html.escape(f.read())
# Arquivos principais do pipeline
arquivos = {
"main.py": "main.py",
"config.py": "config.py",
"validators.py": "validators.py",
"diagnostics.py": "diagnostics.py",
"utils.py": "utils.py",
}
blocks = []
for nome, caminho in arquivos.items():
if not os.path.exists(caminho):
continue
# Cria ID único para cada modal
modal_id = str(uuid.uuid4())
conteudo = read_text(caminho)
# Estrutura HTML do botão + modal
block = f"""
<button onclick="document.getElementById('{modal_id}').style.display='block'"
style="background-color:#006666;color:white;padding:8px 16px;border:none;
border-radius:8px;cursor:pointer;margin:5px;">
📄 {nome}
</button>
<div id="{modal_id}" style="display:none; position:fixed; top:8%; left:10%; width:65%; height:65%;
background-color:white; border:2px solid #333; box-shadow:0 8px 24px rgba(0,0,0,0.18);
padding:20px; overflow:auto; z-index:1000;">
<div style="display:flex; align-items:center; justify-content:space-between;">
<h3 style="margin:0;">{nome}</h3>
<button onclick="document.getElementById('{modal_id}').style.display='none'"
style="background:#333;color:#fff;border:none;border-radius:6px;padding:6px 12px;cursor:pointer;">
Fechar
</button>
</div>
<pre style="white-space:pre-wrap; font-family:monospace; font-size:14px;">{conteudo}</pre>
</div>
"""
blocks.append(block)
# Exibe os modais no notebook
display(HTML("".join(blocks)))
# Execução dentro do notebook
if __name__ == "__main__":
import logging
from utils import setup_logging, read_csv_safely
from validators import run_validations
from config import INPUT_CSV, LOGS_DIR
# Configuração do logger
logger = setup_logging(logs_dir=LOGS_DIR, filename="pipeline.log", level=logging.INFO)
# Leitura e validação do dataset
df = read_csv_safely(INPUT_CSV, logger)
df = run_validations(df, logger)
# Geração dos metadados e exibição dos arquivos
gerar_metadados(df, logger)
visualizar_arquivos_projeto()
2024-11-16 15:25:34,291 | INFO | pipeline_dados | Arquivo CSV carregado com sucesso: dados_vendas.csv (linhas=500, colunas=7)
2024-11-16 15:25:34,292 | INFO | pipeline_dados | Estrutura validada: todas as colunas obrigatórias presentes.
2024-11-16 15:25:34,300 | INFO | pipeline_dados | Coluna 'mes' convertida para datetime64[ns].
2024-11-16 15:25:34,308 | INFO | pipeline_dados | Coluna 'vendedor_id' convertida para category.
2024-11-16 15:25:34,314 | INFO | pipeline_dados | Coluna 'produto_id' convertida para category.
2024-11-16 15:25:34,316 | INFO | pipeline_dados | Coluna 'quantidade' convertida para int64.
2024-11-16 15:25:34,316 | INFO | pipeline_dados | Coluna 'preco_unitario' convertida para float64.
2024-11-16 15:25:34,316 | INFO | pipeline_dados | Coluna 'desconto' convertida para float64.
2024-11-16 15:25:34,316 | INFO | pipeline_dados | Coluna 'valor_total' convertida para float64.
2024-11-16 15:25:34,328 | INFO | pipeline_dados | Dtypes após padronização: {'mes': 'datetime64[ns]', 'vendedor_id': 'category', 'produto_id': 'category', 'quantidade': 'int64', 'preco_unitario': 'float64', 'desconto': 'float64', 'valor_total': 'float64'}
2024-11-16 15:25:34,334 | INFO | pipeline_dados | Regras de negócio validadas sem inconsistências.
2024-11-16 15:25:34,338 | INFO | pipeline_dados | Executando diagnóstico dos dados...
2024-11-16 15:25:34,344 | INFO | pipeline_dados | Coluna 'mes' convertida para datetime com sucesso.
2024-11-16 15:25:34,353 | INFO | pipeline_dados | Metadados exportados para output\metadados\metadados.csv
-------------------->>> 5. Metadados do Dataset <<<--------------------
| Coluna | Descrição | Tipo de Dados | |
|---|---|---|---|
| 0 | mes | Data da venda (mês/ano) | datetime64[ns] |
| 1 | vendedor_id | Identificação do vendedor | category |
| 2 | produto_id | Identificação do produto | category |
| 3 | quantidade | Quantidade vendida | int64 |
| 4 | preco_unitario | Preço unitário do produto | float64 |
| 5 | desconto | Percentual de desconto aplicado | float64 |
| 6 | valor_total | Valor total da venda (após desconto) | float64 |
-------------------->>> Visualização dos Arquivos do Projeto <<<--------------------
6. Qualidade e integridade dos dados
Nesta etapa, o pipeline avalia a qualidade e integridade do dataset de vendas.
São verificadas dimensões, tipos de dados, valores nulos e consistência de colunas críticas, como mes.
Esse processo garante que os dados estejam prontos para análises posteriores, reforçando a confiabilidade do fluxo.
# Item 6 - Qualidade e integridade dos dados
# Configuração do logger
logger = logging.getLogger("diagnostics")
logger.setLevel(logging.INFO)
# Validar e padronizar dataset
df = run_validations(df, logger)
# Exibir moldura
moldura_texto("6. Qualidade e integridade dos dados")
# Executar análise de qualidade e integridade usando função do módulo
metadados = diagnostico_dados(df, logger)
# Exibir dimensões
print("\nDimensões do dataset")
display(pd.DataFrame([metadados["shape"]]))
# Exibir valores nulos
print("\nValores nulos por variável")
display(pd.DataFrame(list(metadados["nulos"].items()), columns=["Variável", "Nulos"]))
# Exibir tipos de dados
print("\nTipos de dados por variável")
display(pd.DataFrame(list(metadados["dtypes"].items()), columns=["Variável", "Tipo de Dados"]))
# Exibir status da conversão de 'mes'
print("\nConversão da coluna 'mes' para datetime")
print(metadados["mes_convertido_para_datetime"])
print("\n")
# Exibir primeiras linhas do dataset validado
df.head()
-------------------->>> 6. Qualidade e integridade dos dados <<<-------------------- Dimensões do dataset
| linhas | colunas | |
|---|---|---|
| 0 | 500 | 7 |
Valores nulos por variável
| Variável | Nulos | |
|---|---|---|
| 0 | mes | 0 |
| 1 | vendedor_id | 0 |
| 2 | produto_id | 0 |
| 3 | quantidade | 0 |
| 4 | preco_unitario | 0 |
| 5 | desconto | 0 |
| 6 | valor_total | 0 |
Tipos de dados por variável
| Variável | Tipo de Dados | |
|---|---|---|
| 0 | mes | datetime64[ns] |
| 1 | vendedor_id | category |
| 2 | produto_id | category |
| 3 | quantidade | int64 |
| 4 | preco_unitario | float64 |
| 5 | desconto | float64 |
| 6 | valor_total | float64 |
Conversão da coluna 'mes' para datetime True
| mes | vendedor_id | produto_id | quantidade | preco_unitario | desconto | valor_total | |
|---|---|---|---|---|---|---|---|
| 0 | 2023-07-31 | 14 | 7 | 68 | 884.87 | 0.06 | 56560.89 |
| 1 | 2023-04-30 | 5 | 8 | 12 | 447.60 | 0.26 | 3974.69 |
| 2 | 2023-11-30 | 12 | 42 | 59 | 337.58 | 0.20 | 15933.78 |
| 3 | 2023-08-31 | 16 | 15 | 37 | 454.29 | 0.09 | 15295.94 |
| 4 | 2023-05-31 | 16 | 47 | 61 | 672.70 | 0.22 | 32007.07 |