Python Admin

Dominando Manipulação de Arquivos em Python: CSV, JSON, XML e Excel com openpyxl em Projetos Reais Já leu

Introdução: Por que dominar manipulação de arquivos? A manipulação de arquivos é uma das habilidades mais práticas e demandadas em programação. Praticamente todo sistema que você construirá precisará ler dados de alguma fonte externa, processá-los e salvar os resultados. Arquivos em formatos como CSV, JSON, XML e Excel são onipresentes no mundo corporativo, em análises de dados, integrações de sistemas e automações. O diferencial de um programador competente não é conhecer apenas a sintaxe, mas entender quando usar cada formato, suas vantagens e desvantagens, além de como manipulá-los de forma eficiente e robusta. Neste artigo, você aprenderá a trabalhar com esses formatos em Python de maneira prática, direto ao ponto, focando em casos de uso reais. Trabalhando com CSV: Estrutura simples e universal CSV (Comma-Separated Values) é um dos formatos mais simples e amplamente adotados. Sua estrutura é basicamente tabular: linhas representam registros e vírgulas separam os campos. A beleza do CSV está na sua universalidade — qualquer editor de

Introdução: Por que dominar manipulação de arquivos?

A manipulação de arquivos é uma das habilidades mais práticas e demandadas em programação. Praticamente todo sistema que você construirá precisará ler dados de alguma fonte externa, processá-los e salvar os resultados. Arquivos em formatos como CSV, JSON, XML e Excel são onipresentes no mundo corporativo, em análises de dados, integrações de sistemas e automações.

O diferencial de um programador competente não é conhecer apenas a sintaxe, mas entender quando usar cada formato, suas vantagens e desvantagens, além de como manipulá-los de forma eficiente e robusta. Neste artigo, você aprenderá a trabalhar com esses formatos em Python de maneira prática, direto ao ponto, focando em casos de uso reais.

Trabalhando com CSV: Estrutura simples e universal

CSV (Comma-Separated Values) é um dos formatos mais simples e amplamente adotados. Sua estrutura é basicamente tabular: linhas representam registros e vírgulas separam os campos. A beleza do CSV está na sua universalidade — qualquer editor de texto consegue abrir, e praticamente toda linguagem de programação tem suporte nativo.

Leitura de arquivos CSV

Python fornece o módulo csv na biblioteca padrão, mas para casos mais complexos, a biblioteca pandas é superior. Vou mostrar ambas as abordagens. A primeira é mais leve e útil quando você não quer dependências externas:

import csv

# Leitura simples com csv nativo
with open('vendas.csv', 'r', encoding='utf-8') as arquivo:
    leitor = csv.DictReader(arquivo)
    for linha in leitor:
        print(f"Produto: {linha['produto']}, Valor: {linha['valor']}")

O DictReader é crucial aqui. Ele transforma cada linha em um dicionário usando os cabeçalhos como chaves, tornando o acesso aos dados muito mais intuitivo do que índices numéricos. Sem ele, você teria que usar índices (linha[0], linha[1]) e o código fica ilegível.

Agora, com pandas (mais poderoso e recomendado para análises):

import pandas as pd

# Leitura com pandas
df = pd.read_csv('vendas.csv')
print(df.head())  # Primeiras 5 linhas
print(df.info())  # Informações sobre tipos de dados
print(df['produto'].unique())  # Valores únicos de uma coluna

A vantagem do pandas é poder fazer filtros, agregações e transformações com uma linha de código. Porém, adiciona dependência. Use pandas quando realmente precisar manipular dados; use csv puro quando apenas ler/escrever.

Escrita em CSV

A escrita é tão simples quanto a leitura:

import csv

dados = [
    {'produto': 'Notebook', 'valor': 2500.00, 'categoria': 'Eletrônicos'},
    {'produto': 'Mouse', 'valor': 50.00, 'categoria': 'Periféricos'},
    {'produto': 'Teclado', 'valor': 150.00, 'categoria': 'Periféricos'}
]

with open('produtos.csv', 'w', newline='', encoding='utf-8') as arquivo:
    campos = ['produto', 'valor', 'categoria']
    escritor = csv.DictWriter(arquivo, fieldnames=campos)

    escritor.writeheader()  # Escreve a linha de cabeçalho
    escritor.writerows(dados)  # Escreve todos os dados

Pontos críticos: use newline='' para evitar linhas em branco extras (comportamento padrão do Python em Windows), defina encoding='utf-8' para caracteres especiais funcionarem corretamente, e sempre especifique fieldnames para garantir a ordem das colunas.

JSON: Flexibilidade e integração de APIs

JSON (JavaScript Object Notation) é o padrão atual para troca de dados entre sistemas e APIs. Sua estrutura de chave-valor permite dados aninhados e mais complexos que CSV. Python trata JSON nativamente através do módulo json, transformando strings JSON em dicionários Python e vice-versa.

Leitura e parsing de JSON

import json

# Leitura de arquivo JSON
with open('config.json', 'r', encoding='utf-8') as arquivo:
    configuracao = json.load(arquivo)

print(configuracao['banco_dados']['host'])
print(configuracao['banco_dados']['porta'])

# Parsing de string JSON
resposta_api = '{"status": "sucesso", "dados": [1, 2, 3]}'
dados = json.loads(resposta_api)
print(dados['status'])

A distinção importante: json.load() lê direto de um arquivo, enquanto json.loads() (note o 's') parseia uma string. Use a primeira quando trabalhar com arquivos, a segunda ao processar respostas de APIs.

Escrita e geração de JSON

import json
from datetime import datetime

# Dados Python (dicionários e listas)
usuario = {
    'id': 1,
    'nome': 'João Silva',
    'email': 'joao@example.com',
    'tags': ['admin', 'desenvolvedor'],
    'ativo': True,
    'criado_em': datetime.now().isoformat()
}

# Escrita em arquivo
with open('usuario.json', 'w', encoding='utf-8') as arquivo:
    json.dump(usuario, arquivo, indent=2, ensure_ascii=False)

# Conversão para string (sem escrever em arquivo)
json_string = json.dumps(usuario, indent=2, ensure_ascii=False)
print(json_string)

Os parâmetros indent=2 formatam o JSON com identação legível (fundamental para debugar), e ensure_ascii=False permite caracteres acentuados. Sem este último, você verá \u00e3 no lugar de ã.

Tratamento de erros e dados complexos

JSON tem limitações: não suporta datas, funções ou tipos customizados nativamente. Para contornar isso:

import json
from datetime import datetime
from decimal import Decimal

class Encoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, Decimal):
            return float(obj)
        return super().default(obj)

dados = {
    'valor': Decimal('19.99'),
    'data': datetime(2024, 1, 15)
}

json_string = json.dumps(dados, cls=Encoder, indent=2)
print(json_string)

Criando um encoder customizado, você define como objetos não-serializáveis devem ser tratados. Isso é essencial ao trabalhar com APIs que exigem tipos específicos.

XML: Hierarquia e validação em dados estruturados

XML é mais verboso que JSON e CSV, mas oferece suporte a validação por schema, namespaces e é ainda amplamente usado em integrações corporativas legadas. Python oferece múltiplas bibliotecas; vou focar na xml.etree.ElementTree, que vem na biblioteca padrão.

Leitura de XML

import xml.etree.ElementTree as ET

# Parse de arquivo XML
tree = ET.parse('pedidos.xml')
raiz = tree.getroot()

# Iteração simples
for pedido in raiz.findall('pedido'):
    numero = pedido.find('numero').text
    cliente = pedido.find('cliente').text
    print(f"Pedido {numero}: {cliente}")

# Acesso com namespaces
arquivo_ns = ET.parse('documento_ns.xml')
ns = {'ex': 'http://example.com/schema'}
for item in arquivo_ns.findall('ex:item', ns):
    print(item.text)

A hierarquia XML é natural com Element Tree. Use find() para um elemento, findall() para múltiplos, e .text para obter o conteúdo. Namespaces exigem dicionários específicos no findall().

Escrita de XML

import xml.etree.ElementTree as ET

# Criar raiz
raiz = ET.Element('catalogo')

# Adicionar elementos filhos
for i, produto in enumerate([
    {'nome': 'Laptop', 'preco': 2000},
    {'nome': 'Mouse', 'preco': 45}
], 1):
    elem_produto = ET.SubElement(raiz, 'produto')
    elem_produto.set('id', str(i))

    elem_nome = ET.SubElement(elem_produto, 'nome')
    elem_nome.text = produto['nome']

    elem_preco = ET.SubElement(elem_produto, 'preco')
    elem_preco.text = str(produto['preco'])

# Escrever em arquivo com indentação
tree = ET.ElementTree(raiz)
tree.write('catalogo.xml', encoding='utf-8', xml_declaration=True)

XML gerado fica sem formatação por padrão em ElementTree. Para visualizar com indentação:

def indentar(elem, nivel=0):
    indent = "\n" + "  " * nivel
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = indent + "  "
        if not elem.tail or not elem.tail.strip():
            elem.tail = indent
        for child in elem:
            indentar(child, nivel + 1)
        if not child.tail or not child.tail.strip():
            child.tail = indent
    else:
        if nivel and (not elem.tail or not elem.tail.strip()):
            elem.tail = indent

indentar(raiz)
tree = ET.ElementTree(raiz)
tree.write('catalogo_formatado.xml', encoding='utf-8', xml_declaration=True)

Não é elegante, mas funciona. Bibliotecas como lxml fazem isso automaticamente, mas exigem instalação externa.

Excel com openpyxl: Manipulação profissional de planilhas

Arquivos Excel (.xlsx) são ubíquos em negócios. openpyxl é a biblioteca padrão para ler e escrever Excel em Python, suportando formatação, fórmulas, gráficos e validação.

Instalação e conceitos básicos

pip install openpyxl

Um arquivo Excel é uma coleção de sheets (abas). Cada sheet tem células organizadas em linhas e colunas. Você acessa células por índice numérico (A1, B2) ou por coordenadas (1, 1).

Leitura de Excel

from openpyxl import load_workbook

# Carregar workbook
wb = load_workbook('relatorio.xlsx')

# Acessar sheet ativa ou por nome
ws = wb.active
# ou: ws = wb['Vendas']

# Ler célula individual
valor = ws['A1'].value
valor_alt = ws.cell(row=1, column=1).value

# Iterar sobre linhas
for linha in ws.iter_rows(min_row=2, max_row=10, values_only=True):
    print(linha)

# Obter todas as linhas com dados
for linha in ws.iter_rows(values_only=True):
    if any(linha):  # Ignora linhas vazias
        print(linha)

wb.close()

iter_rows(values_only=True) retorna apenas os valores das células. Sem values_only=True, retorna objetos Cell, úteis quando você precisa de formatação ou fórmulas.

Escrita e criação de planilhas

from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment

# Criar novo workbook
wb = Workbook()
ws = wb.active
ws.title = "Produtos"

# Escrever dados simples
ws['A1'] = 'Produto'
ws['B1'] = 'Quantidade'
ws['C1'] = 'Preço'

# Dados
produtos = [
    ('Notebook', 5, 2500.00),
    ('Mouse', 20, 50.00),
    ('Teclado', 15, 150.00)
]

for idx, (produto, qtd, preco) in enumerate(produtos, start=2):
    ws[f'A{idx}'] = produto
    ws[f'B{idx}'] = qtd
    ws[f'C{idx}'] = preco

# Aplicar formatação ao cabeçalho
font_negrito = Font(bold=True, color="FFFFFF")
preenchimento_azul = PatternFill(start_color="0070C0", end_color="0070C0", fill_type="solid")
alinhamento_centro = Alignment(horizontal="center", vertical="center")

for celula in ['A1', 'B1', 'C1']:
    ws[celula].font = font_negrito
    ws[celula].fill = preenchimento_azul
    ws[celula].alignment = alinhamento_centro

# Ajustar largura das colunas
ws.column_dimensions['A'].width = 20
ws.column_dimensions['B'].width = 15
ws.column_dimensions['C'].width = 15

# Salvar
wb.save('produtos.xlsx')

Formatação é onde openpyxl brilha. Você consegue definir fontes, cores, bordas, alinhamentos e muito mais programaticamente.

Fórmulas e dados dinâmicos

from openpyxl import load_workbook

wb = load_workbook('vendas.xlsx')
ws = wb.active

# Adicionar fórmulas
ws['D1'] = 'Total'
ws['D2'] = '=B2*C2'  # Multiplica quantidade por preço
ws['D3'] = '=B3*C3'

# Fórmulas com referências a ranges
ws['E1'] = 'Subtotal'
ws['E5'] = '=SUM(D2:D4)'  # Soma os totais

# Colunas calculadas com Python (melhor para dados estáticos)
for row in range(2, 5):
    qtd = ws[f'B{row}'].value
    preco = ws[f'C{row}'].value
    ws[f'D{row}'].value = qtd * preco

wb.save('vendas_processado.xlsx')

Use fórmulas quando os dados serão atualizados no Excel posteriormente. Use cálculos Python quando os dados são estáticos e você não quer que o usuário altere a fórmula acidentalmente.

Leitura e processamento avançado

from openpyxl import load_workbook
from openpyxl.utils import get_column_letter

wb = load_workbook('dados.xlsx')
ws = wb.active

# Obter dimensões da planilha
max_linha = ws.max_row
max_coluna = ws.max_column

# Construir dicionário a partir de dados com cabeçalho
dados = []
cabecalhos = []

# Ler cabeçalhos
for col in range(1, max_coluna + 1):
    cabecalho = ws.cell(row=1, column=col).value
    cabecalhos.append(cabecalho)

# Ler dados
for linha in range(2, max_linha + 1):
    registro = {}
    for col in range(1, max_coluna + 1):
        valor = ws.cell(row=linha, column=col).value
        registro[cabecalhos[col - 1]] = valor
    dados.append(registro)

# Processar dados
for registro in dados:
    print(f"{registro['nome']} - {registro['valor']}")

wb.close()

Essa abordagem transforma uma planilha em uma lista de dicionários, similar ao DictReader do CSV, facilitando processamento posterior.

Comparação prática: quando usar cada formato

Cada formato tem seu lugar. CSV é ideal para dados tabulares simples e troca de dados entre sistemas; é leve, universal e fácil de debugar. JSON é perfeito para APIs, configurações e dados hierárquicos; é legível e oferece flexibilidade estrutural. XML ainda é usado em integrações corporativas legadas e onde validação de schema é obrigatória; é verboso mas poderoso.

Excel é a escolha quando você precisa enviar dados para usuários não-técnicos, gráficos, formatação visual ou quando a empresa já trabalha com planilhas. Não force usuários de negócio a aprender Python; envie um Excel bem formatado.

# Exemplo integrado: ler CSV, processar, salvar em JSON e Excel
import csv
import json
from openpyxl import Workbook

# 1. Ler CSV
dados_processados = []
with open('entrada.csv', 'r', encoding='utf-8') as f:
    leitor = csv.DictReader(f)
    for linha in leitor:
        # Processar dados
        linha['valor_total'] = float(linha['quantidade']) * float(linha['preco'])
        dados_processados.append(linha)

# 2. Salvar em JSON
with open('resultado.json', 'w', encoding='utf-8') as f:
    json.dump(dados_processados, f, indent=2, ensure_ascii=False)

# 3. Salvar em Excel
wb = Workbook()
ws = wb.active
ws.append(['Produto', 'Quantidade', 'Preço', 'Total'])
for dado in dados_processados:
    ws.append([dado['produto'], dado['quantidade'], dado['preco'], dado['valor_total']])
wb.save('resultado.xlsx')

Tratamento de erros e boas práticas

Trabalhar com arquivos sempre envolve riscos: arquivo não existe, permissões insuficientes, dados malformados. Código robusto trata esses cenários:

import csv
import json
from openpyxl import load_workbook

# Leitura segura de CSV
def ler_csv_seguro(caminho):
    try:
        with open(caminho, 'r', encoding='utf-8') as f:
            return list(csv.DictReader(f))
    except FileNotFoundError:
        print(f"Erro: arquivo '{caminho}' não encontrado")
        return []
    except UnicodeDecodeError:
        print(f"Erro: problema de codificação. Tentando com latin-1...")
        with open(caminho, 'r', encoding='latin-1') as f:
            return list(csv.DictReader(f))
    except Exception as e:
        print(f"Erro inesperado: {e}")
        return []

# JSON com validação
def ler_json_seguro(caminho):
    try:
        with open(caminho, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"Erro: arquivo '{caminho}' não encontrado")
        return None
    except json.JSONDecodeError as e:
        print(f"Erro: JSON inválido - {e}")
        return None

# Excel com backup
def salvar_excel_seguro(workbook, caminho):
    import shutil
    from pathlib import Path

    # Fazer backup do arquivo anterior se existir
    if Path(caminho).exists():
        shutil.copy(caminho, f"{caminho}.backup")

    try:
        workbook.save(caminho)
        print(f"Arquivo salvo com sucesso: {caminho}")
    except PermissionError:
        print(f"Erro: sem permissão para escrever em '{caminho}'")
    except Exception as e:
        print(f"Erro ao salvar: {e}")

# Usar as funções
dados = ler_csv_seguro('dados.csv')
config = ler_json_seguro('config.json')

Pontos-chave: sempre use context managers (with), trate exceções específicas (não genéricas), registre erros de forma útil para debugging, e considere backup de dados críticos.

Conclusão

Dominar manipulação de arquivos em Python significa entender três competências interdependentes. Primeiro, conhecer as características e limitações de cada formato: CSV para simplicidade, JSON para flexibilidade, XML para validação estruturada, e Excel para comunicação com usuários não-técnicos. Segundo, saber escolher a biblioteca certa para o trabalho — módulos nativos para tarefas simples, pandas e openpyxl quando precisar de funcionalidades avançadas. Terceiro, sempre escrever código defensivo que trata erros e valida dados, porque dados do mundo real são bagunçados.

O caminho para domínio é praticar com dados reais. Pegue um arquivo CSV de um site como Kaggle, processe-o, converta para JSON, crie uma planilha Excel formatada — esse fluxo prático solidifica seu entendimento de forma que nenhuma leitura de documentação consegue.

Referências


Artigos relacionados