Python

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

19 min de leitura

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

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

<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(&#039;vendas.csv&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as arquivo:

leitor = csv.DictReader(arquivo)

for linha in leitor:

print(f&quot;Produto: {linha[&#039;produto&#039;]}, Valor: {linha[&#039;valor&#039;]}&quot;)</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(&#039;vendas.csv&#039;)

print(df.head()) # Primeiras 5 linhas

print(df.info()) # Informações sobre tipos de dados

print(df[&#039;produto&#039;].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 = [

{&#039;produto&#039;: &#039;Notebook&#039;, &#039;valor&#039;: 2500.00, &#039;categoria&#039;: &#039;Eletrônicos&#039;},

{&#039;produto&#039;: &#039;Mouse&#039;, &#039;valor&#039;: 50.00, &#039;categoria&#039;: &#039;Periféricos&#039;},

{&#039;produto&#039;: &#039;Teclado&#039;, &#039;valor&#039;: 150.00, &#039;categoria&#039;: &#039;Periféricos&#039;}

]

with open(&#039;produtos.csv&#039;, &#039;w&#039;, newline=&#039;&#039;, encoding=&#039;utf-8&#039;) as arquivo:

campos = [&#039;produto&#039;, &#039;valor&#039;, &#039;categoria&#039;]

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=&#039;&#039;</code> para evitar linhas em branco extras (comportamento padrão do Python em Windows), defina <code>encoding=&#039;utf-8&#039;</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(&#039;config.json&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as arquivo:

configuracao = json.load(arquivo)

print(configuracao[&#039;banco_dados&#039;][&#039;host&#039;])

print(configuracao[&#039;banco_dados&#039;][&#039;porta&#039;])

Parsing de string JSON

resposta_api = &#039;{&quot;status&quot;: &quot;sucesso&quot;, &quot;dados&quot;: [1, 2, 3]}&#039;

dados = json.loads(resposta_api)

print(dados[&#039;status&#039;])</code></pre>

<p>A distinção importante: <code>json.load()</code> lê direto de um arquivo, enquanto <code>json.loads()</code> (note o &#039;s&#039;) 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 = {

&#039;id&#039;: 1,

&#039;nome&#039;: &#039;João Silva&#039;,

&#039;email&#039;: &#039;joao@example.com&#039;,

&#039;tags&#039;: [&#039;admin&#039;, &#039;desenvolvedor&#039;],

&#039;ativo&#039;: True,

&#039;criado_em&#039;: datetime.now().isoformat()

}

Escrita em arquivo

with open(&#039;usuario.json&#039;, &#039;w&#039;, encoding=&#039;utf-8&#039;) 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 = {

&#039;valor&#039;: Decimal(&#039;19.99&#039;),

&#039;data&#039;: 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(&#039;pedidos.xml&#039;)

raiz = tree.getroot()

Iteração simples

for pedido in raiz.findall(&#039;pedido&#039;):

numero = pedido.find(&#039;numero&#039;).text

cliente = pedido.find(&#039;cliente&#039;).text

print(f&quot;Pedido {numero}: {cliente}&quot;)

Acesso com namespaces

arquivo_ns = ET.parse(&#039;documento_ns.xml&#039;)

ns = {&#039;ex&#039;: &#039;http://example.com/schema&#039;}

for item in arquivo_ns.findall(&#039;ex:item&#039;, 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(&#039;catalogo&#039;)

Adicionar elementos filhos

for i, produto in enumerate([

{&#039;nome&#039;: &#039;Laptop&#039;, &#039;preco&#039;: 2000},

{&#039;nome&#039;: &#039;Mouse&#039;, &#039;preco&#039;: 45}

], 1):

elem_produto = ET.SubElement(raiz, &#039;produto&#039;)

elem_produto.set(&#039;id&#039;, str(i))

elem_nome = ET.SubElement(elem_produto, &#039;nome&#039;)

elem_nome.text = produto[&#039;nome&#039;]

elem_preco = ET.SubElement(elem_produto, &#039;preco&#039;)

elem_preco.text = str(produto[&#039;preco&#039;])

Escrever em arquivo com indentação

tree = ET.ElementTree(raiz)

tree.write(&#039;catalogo.xml&#039;, encoding=&#039;utf-8&#039;, 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 = &quot;\n&quot; + &quot; &quot; * nivel

if len(elem):

if not elem.text or not elem.text.strip():

elem.text = indent + &quot; &quot;

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(&#039;catalogo_formatado.xml&#039;, encoding=&#039;utf-8&#039;, 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(&#039;relatorio.xlsx&#039;)

Acessar sheet ativa ou por nome

ws = wb.active

ou: ws = wb[&#039;Vendas&#039;]

Ler célula individual

valor = ws[&#039;A1&#039;].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 = &quot;Produtos&quot;

Escrever dados simples

ws[&#039;A1&#039;] = &#039;Produto&#039;

ws[&#039;B1&#039;] = &#039;Quantidade&#039;

ws[&#039;C1&#039;] = &#039;Preço&#039;

Dados

produtos = [

(&#039;Notebook&#039;, 5, 2500.00),

(&#039;Mouse&#039;, 20, 50.00),

(&#039;Teclado&#039;, 15, 150.00)

]

for idx, (produto, qtd, preco) in enumerate(produtos, start=2):

ws[f&#039;A{idx}&#039;] = produto

ws[f&#039;B{idx}&#039;] = qtd

ws[f&#039;C{idx}&#039;] = preco

Aplicar formatação ao cabeçalho

font_negrito = Font(bold=True, color=&quot;FFFFFF&quot;)

preenchimento_azul = PatternFill(start_color=&quot;0070C0&quot;, end_color=&quot;0070C0&quot;, fill_type=&quot;solid&quot;)

alinhamento_centro = Alignment(horizontal=&quot;center&quot;, vertical=&quot;center&quot;)

for celula in [&#039;A1&#039;, &#039;B1&#039;, &#039;C1&#039;]:

ws[celula].font = font_negrito

ws[celula].fill = preenchimento_azul

ws[celula].alignment = alinhamento_centro

Ajustar largura das colunas

ws.column_dimensions[&#039;A&#039;].width = 20

ws.column_dimensions[&#039;B&#039;].width = 15

ws.column_dimensions[&#039;C&#039;].width = 15

Salvar

wb.save(&#039;produtos.xlsx&#039;)</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(&#039;vendas.xlsx&#039;)

ws = wb.active

Adicionar fórmulas

ws[&#039;D1&#039;] = &#039;Total&#039;

ws[&#039;D2&#039;] = &#039;=B2*C2&#039; # Multiplica quantidade por preço

ws[&#039;D3&#039;] = &#039;=B3*C3&#039;

Fórmulas com referências a ranges

ws[&#039;E1&#039;] = &#039;Subtotal&#039;

ws[&#039;E5&#039;] = &#039;=SUM(D2:D4)&#039; # Soma os totais

Colunas calculadas com Python (melhor para dados estáticos)

for row in range(2, 5):

qtd = ws[f&#039;B{row}&#039;].value

preco = ws[f&#039;C{row}&#039;].value

ws[f&#039;D{row}&#039;].value = qtd * preco

wb.save(&#039;vendas_processado.xlsx&#039;)</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(&#039;dados.xlsx&#039;)

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&quot;{registro[&#039;nome&#039;]} - {registro[&#039;valor&#039;]}&quot;)

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(&#039;entrada.csv&#039;, &#039;r&#039;, encoding=&#039;utf-8&#039;) as f:

leitor = csv.DictReader(f)

for linha in leitor:

Processar dados

linha[&#039;valor_total&#039;] = float(linha[&#039;quantidade&#039;]) * float(linha[&#039;preco&#039;])

dados_processados.append(linha)

2. Salvar em JSON

with open(&#039;resultado.json&#039;, &#039;w&#039;, encoding=&#039;utf-8&#039;) as f:

json.dump(dados_processados, f, indent=2, ensure_ascii=False)

3. Salvar em Excel

wb = Workbook()

ws = wb.active

ws.append([&#039;Produto&#039;, &#039;Quantidade&#039;, &#039;Preço&#039;, &#039;Total&#039;])

for dado in dados_processados:

ws.append([dado[&#039;produto&#039;], dado[&#039;quantidade&#039;], dado[&#039;preco&#039;], dado[&#039;valor_total&#039;]])

wb.save(&#039;resultado.xlsx&#039;)</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, &#039;r&#039;, encoding=&#039;utf-8&#039;) as f:

return list(csv.DictReader(f))

except FileNotFoundError:

print(f&quot;Erro: arquivo &#039;{caminho}&#039; não encontrado&quot;)

return []

except UnicodeDecodeError:

print(f&quot;Erro: problema de codificação. Tentando com latin-1...&quot;)

with open(caminho, &#039;r&#039;, encoding=&#039;latin-1&#039;) as f:

return list(csv.DictReader(f))

except Exception as e:

print(f&quot;Erro inesperado: {e}&quot;)

return []

JSON com validação

def ler_json_seguro(caminho):

try:

with open(caminho, &#039;r&#039;, encoding=&#039;utf-8&#039;) as f:

return json.load(f)

except FileNotFoundError:

print(f&quot;Erro: arquivo &#039;{caminho}&#039; não encontrado&quot;)

return None

except json.JSONDecodeError as e:

print(f&quot;Erro: JSON inválido - {e}&quot;)

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&quot;{caminho}.backup&quot;)

try:

workbook.save(caminho)

print(f&quot;Arquivo salvo com sucesso: {caminho}&quot;)

except PermissionError:

print(f&quot;Erro: sem permissão para escrever em &#039;{caminho}&#039;&quot;)

except Exception as e:

print(f&quot;Erro ao salvar: {e}&quot;)

Usar as funções

dados = ler_csv_seguro(&#039;dados.csv&#039;)

config = ler_json_seguro(&#039;config.json&#039;)</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>&lt;!-- FIM --&gt;</p>

Comentários

Mais em Python

Como Usar Introdução ao Python: Filosofia, Instalação, pyenv e Primeiro Script em Produção
Como Usar Introdução ao Python: Filosofia, Instalação, pyenv e Primeiro Script em Produção

A Filosofia do Python Python é uma linguagem de programação nascida em 1989,...

Como Usar Strings em Python: Métodos, f-strings, raw strings e Formatação em Produção
Como Usar Strings em Python: Métodos, f-strings, raw strings e Formatação em Produção

Introdução: Por Que Dominar Strings em Python? Strings são um dos tipos de da...

Logging em Python: logging module, structlog e Boas Práticas: Do Básico ao Avançado
Logging em Python: logging module, structlog e Boas Práticas: Do Básico ao Avançado

O módulo logging nativo do Python O módulo é parte da biblioteca padrão do Py...