<h2>Introdução: Por que dominar manipulação de arquivos?</h2>
<p>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.</p>
<p>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.</p>
<h2>Trabalhando com CSV: Estrutura simples e universal</h2>
<p>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.</p>
<h3>Leitura de arquivos CSV</h3>
<p>Python fornece o módulo <code>csv</code> na biblioteca padrão, mas para casos mais complexos, a biblioteca <code>pandas</code> é superior. Vou mostrar ambas as abordagens. A primeira é mais leve e útil quando você não quer dependências externas:</p>
<pre><code class="language-python">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']}")</code></pre>
<p>O <code>DictReader</code> é 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.</p>
<p>Agora, com pandas (mais poderoso e recomendado para análises):</p>
<pre><code class="language-python">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</code></pre>
<p>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.</p>
<h3>Escrita em CSV</h3>
<p>A escrita é tão simples quanto a leitura:</p>
<pre><code class="language-python">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</code></pre>
<p>Pontos críticos: use <code>newline=''</code> para evitar linhas em branco extras (comportamento padrão do Python em Windows), defina <code>encoding='utf-8'</code> para caracteres especiais funcionarem corretamente, e sempre especifique <code>fieldnames</code> para garantir a ordem das colunas.</p>
<h2>JSON: Flexibilidade e integração de APIs</h2>
<p>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 <code>json</code>, transformando strings JSON em dicionários Python e vice-versa.</p>
<h3>Leitura e parsing de JSON</h3>
<pre><code class="language-python">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'])</code></pre>
<p>A distinção importante: <code>json.load()</code> lê direto de um arquivo, enquanto <code>json.loads()</code> (note o 's') parseia uma string. Use a primeira quando trabalhar com arquivos, a segunda ao processar respostas de APIs.</p>
<h3>Escrita e geração de JSON</h3>
<pre><code class="language-python">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)</code></pre>
<p>Os parâmetros <code>indent=2</code> formatam o JSON com identação legível (fundamental para debugar), e <code>ensure_ascii=False</code> permite caracteres acentuados. Sem este último, você verá <code>\u00e3</code> no lugar de <code>ã</code>.</p>
<h3>Tratamento de erros e dados complexos</h3>
<p>JSON tem limitações: não suporta datas, funções ou tipos customizados nativamente. Para contornar isso:</p>
<pre><code class="language-python">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)</code></pre>
<p>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.</p>
<h2>XML: Hierarquia e validação em dados estruturados</h2>
<p>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 <code>xml.etree.ElementTree</code>, que vem na biblioteca padrão.</p>
<h3>Leitura de XML</h3>
<pre><code class="language-python">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)</code></pre>
<p>A hierarquia XML é natural com Element Tree. Use <code>find()</code> para um elemento, <code>findall()</code> para múltiplos, e <code>.text</code> para obter o conteúdo. Namespaces exigem dicionários específicos no <code>findall()</code>.</p>
<h3>Escrita de XML</h3>
<pre><code class="language-python">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)</code></pre>
<p>XML gerado fica sem formatação por padrão em ElementTree. Para visualizar com indentação:</p>
<pre><code class="language-python">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)</code></pre>
<p>Não é elegante, mas funciona. Bibliotecas como <code>lxml</code> fazem isso automaticamente, mas exigem instalação externa.</p>
<h2>Excel com openpyxl: Manipulação profissional de planilhas</h2>
<p>Arquivos Excel (.xlsx) são ubíquos em negócios. <code>openpyxl</code> é a biblioteca padrão para ler e escrever Excel em Python, suportando formatação, fórmulas, gráficos e validação.</p>
<h3>Instalação e conceitos básicos</h3>
<pre><code class="language-bash">pip install openpyxl</code></pre>
<p>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).</p>
<h3>Leitura de Excel</h3>
<pre><code class="language-python">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()</code></pre>
<p><code>iter_rows(values_only=True)</code> retorna apenas os valores das células. Sem <code>values_only=True</code>, retorna objetos Cell, úteis quando você precisa de formatação ou fórmulas.</p>
<h3>Escrita e criação de planilhas</h3>
<pre><code class="language-python">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')</code></pre>
<p>Formatação é onde openpyxl brilha. Você consegue definir fontes, cores, bordas, alinhamentos e muito mais programaticamente.</p>
<h3>Fórmulas e dados dinâmicos</h3>
<pre><code class="language-python">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')</code></pre>
<p>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.</p>
<h3>Leitura e processamento avançado</h3>
<pre><code class="language-python">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()</code></pre>
<p>Essa abordagem transforma uma planilha em uma lista de dicionários, similar ao <code>DictReader</code> do CSV, facilitando processamento posterior.</p>
<h2>Comparação prática: quando usar cada formato</h2>
<p>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.</p>
<p>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.</p>
<pre><code class="language-python"># 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')</code></pre>
<h2>Tratamento de erros e boas práticas</h2>
<p>Trabalhar com arquivos sempre envolve riscos: arquivo não existe, permissões insuficientes, dados malformados. Código robusto trata esses cenários:</p>
<pre><code class="language-python">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')</code></pre>
<p>Pontos-chave: sempre use context managers (<code>with</code>), trate exceções específicas (não genéricas), registre erros de forma útil para debugging, e considere backup de dados críticos.</p>
<h2>Conclusão</h2>
<p>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.</p>
<p>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.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://docs.python.org/3/library/csv.html" target="_blank" rel="noopener noreferrer">Documentação oficial do módulo csv — Python.org</a></li>
<li><a href="https://docs.python.org/3/library/json.html" target="_blank" rel="noopener noreferrer">Documentação oficial do módulo json — Python.org</a></li>
<li><a href="https://docs.python.org/3/library/xml.etree.elementtree.html" target="_blank" rel="noopener noreferrer">Documentação oficial de xml.etree.ElementTree — Python.org</a></li>
<li><a href="https://openpyxl.readthedocs.io/" target="_blank" rel="noopener noreferrer">Documentação oficial do openpyxl — readthedocs.io</a></li>
<li><a href="https://realpython.com/python-csv/" target="_blank" rel="noopener noreferrer">Real Python: Working with CSV files in Python</a></li>
</ul>
<p><!-- FIM --></p>