Trabalhando com CSV e JSON em Python
1. Introdução aos Formatos CSV e JSON
CSV (Comma-Separated Values) é um formato tabular simples onde cada linha representa um registro e os campos são separados por vírgulas. É ideal para dados planos como planilhas, relatórios financeiros e exportações de bancos de dados relacionais.
JSON (JavaScript Object Notation) é um formato hierárquico que suporta estruturas aninhadas como listas e dicionários. É amplamente usado em APIs web, arquivos de configuração e armazenamento de dados complexos.
Quando usar cada formato:
- CSV: dados tabulares simples, grandes volumes de dados numéricos, interoperabilidade com Excel e bancos de dados
- JSON: dados com hierarquia, objetos aninhados, APIs REST, configurações de aplicações
2. Lendo e Escrevendo Arquivos CSV com o Módulo csv
O módulo csv da biblioteca padrão oferece ferramentas robustas para manipulação de arquivos CSV.
Leitura básica com csv.reader()
import csv
# Leitura básica
with open('dados.csv', 'r', encoding='utf-8') as arquivo:
leitor = csv.reader(arquivo)
for linha in leitor:
print(linha) # Cada linha é uma lista
Escrita básica com csv.writer()
with open('saida.csv', 'w', newline='', encoding='utf-8') as arquivo:
escritor = csv.writer(arquivo)
escritor.writerow(['Nome', 'Idade', 'Cidade'])
escritor.writerow(['Ana', 28, 'São Paulo'])
escritor.writerow(['Carlos', 35, 'Rio de Janeiro'])
Trabalhando com dicionários: DictReader e DictWriter
# Leitura com DictReader (cabeçalho como chaves)
with open('dados.csv', 'r', encoding='utf-8') as arquivo:
leitor = csv.DictReader(arquivo)
for linha in leitor:
print(linha['Nome'], linha['Idade'])
# Escrita com DictWriter
with open('saida.csv', 'w', newline='', encoding='utf-8') as arquivo:
campos = ['Nome', 'Idade', 'Cidade']
escritor = csv.DictWriter(arquivo, fieldnames=campos)
escritor.writeheader()
escritor.writerow({'Nome': 'Ana', 'Idade': 28, 'Cidade': 'São Paulo'})
3. Configurações Avançadas para CSV
Delimitadores personalizados
import csv
# CSV com ponto e vírgula (comum em português)
with open('dados_pt.csv', 'r', encoding='utf-8') as arquivo:
leitor = csv.reader(arquivo, delimiter=';')
for linha in leitor:
print(linha)
# CSV com tabulação
with open('dados_tsv.tsv', 'r', encoding='utf-8') as arquivo:
leitor = csv.reader(arquivo, delimiter='\t')
# ou use: leitor = csv.reader(arquivo, dialect=csv.excel_tab)
Lidando com citações e valores especiais
with open('dados.csv', 'w', newline='', encoding='utf-8') as arquivo:
escritor = csv.writer(arquivo,
quoting=csv.QUOTE_ALL, # Cita todos os campos
quotechar='"', # Caractere de citação
escapechar='\\') # Caractere de escape
escritor.writerow(['Nome contém, vírgula', 'Valor "especial"', 123])
Tratamento de valores ausentes
with open('dados_incompletos.csv', 'r', encoding='utf-8') as arquivo:
leitor = csv.reader(arquivo)
for num_linha, linha in enumerate(leitor, 1):
# Verifica número de colunas esperado
if len(linha) < 3:
print(f"Linha {num_linha} incompleta: {linha}")
continue
# Substitui valores vazios por None
linha_tratada = [None if campo == '' else campo for campo in linha]
print(linha_tratada)
4. Lendo e Escrevendo Arquivos JSON com o Módulo json
Serialização: json.dumps() e json.dump()
import json
dados = {
'nome': 'Ana',
'idade': 28,
'cidades': ['São Paulo', 'Rio de Janeiro'],
'ativo': True
}
# Para string
json_string = json.dumps(dados, indent=2, sort_keys=True, ensure_ascii=False)
print(json_string)
# Para arquivo
with open('dados.json', 'w', encoding='utf-8') as arquivo:
json.dump(dados, arquivo, indent=2, ensure_ascii=False)
Desserialização: json.loads() e json.load()
# De string
json_string = '{"nome": "Carlos", "idade": 35}'
dados = json.loads(json_string)
print(dados['nome'])
# De arquivo
with open('dados.json', 'r', encoding='utf-8') as arquivo:
dados = json.load(arquivo)
print(dados)
Parâmetros úteis
# indent: formatação legível
# sort_keys: ordena chaves alfabeticamente
# ensure_ascii=False: preserva caracteres acentuados
json.dumps(dados, indent=4, sort_keys=True, ensure_ascii=False)
5. Trabalhando com Dados JSON Complexos
Navegando por estruturas aninhadas
dados_complexos = {
'empresa': 'TechCorp',
'funcionarios': [
{'nome': 'Ana', 'cargo': 'Dev', 'skills': ['Python', 'Django']},
{'nome': 'Carlos', 'cargo': 'Analista', 'skills': ['SQL', 'Excel']}
],
'metadados': {
'versao': 1.0,
'ultima_atualizacao': '2024-01-15'
}
}
# Navegação segura
for func in dados_complexos.get('funcionarios', []):
nome = func.get('nome', 'Desconhecido')
skills = ', '.join(func.get('skills', []))
print(f"{nome}: {skills}")
Convertendo objetos Python para JSON
from datetime import datetime
class Pessoa:
def __init__(self, nome, nascimento):
self.nome = nome
self.nascimento = nascimento
def converter_para_json(obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, Pessoa):
return {'nome': obj.nome, 'nascimento': obj.nascimento.isoformat()}
raise TypeError(f"Tipo não serializável: {type(obj)}")
pessoa = Pessoa('Maria', datetime(1990, 5, 15))
json_string = json.dumps(pessoa, default=converter_para_json, indent=2)
print(json_string)
Convertendo JSON de volta para objetos personalizados
def criar_pessoa(dicionario):
if 'nascimento' in dicionario:
dicionario['nascimento'] = datetime.fromisoformat(dicionario['nascimento'])
return Pessoa(**dicionario)
json_string = '{"nome": "Maria", "nascimento": "1990-05-15T00:00:00"}'
pessoa = json.loads(json_string, object_hook=criar_pessoa)
print(pessoa.nome, pessoa.nascimento)
6. Tratamento de Erros e Validação
Exceções comuns
import json
import csv
# Tratamento de erros em JSON
try:
with open('dados.json', 'r', encoding='utf-8') as arquivo:
dados = json.load(arquivo)
except FileNotFoundError:
print("Arquivo não encontrado")
except json.JSONDecodeError as e:
print(f"Erro de decodificação JSON: {e}")
# Tratamento de erros em CSV
try:
with open('dados.csv', 'r', encoding='utf-8') as arquivo:
leitor = csv.reader(arquivo)
for linha in leitor:
if len(linha) != 3:
raise ValueError(f"Linha inválida: esperado 3 colunas, encontrado {len(linha)}")
except csv.Error as e:
print(f"Erro no CSV: {e}")
Validação de dados JSON
def validar_usuario(dados):
obrigatorios = ['nome', 'email', 'idade']
for campo in obrigatorios:
if campo not in dados:
raise ValueError(f"Campo obrigatório ausente: {campo}")
if not isinstance(dados.get('idade'), (int, float)):
raise TypeError("Idade deve ser numérica")
if dados['idade'] < 0 or dados['idade'] > 150:
raise ValueError("Idade fora do intervalo válido")
return True
# Uso
try:
dados = json.loads('{"nome": "Ana", "email": "ana@email.com", "idade": 28}')
validar_usuario(dados)
print("Dados válidos")
except (json.JSONDecodeError, ValueError, TypeError) as e:
print(f"Erro de validação: {e}")
7. Conversão Entre CSV e JSON
CSV para JSON
import csv
import json
def csv_para_json(arquivo_csv, arquivo_json):
with open(arquivo_csv, 'r', encoding='utf-8') as csv_file:
leitor = csv.DictReader(csv_file)
dados = list(leitor)
with open(arquivo_json, 'w', encoding='utf-8') as json_file:
json.dump(dados, json_file, indent=2, ensure_ascii=False)
print(f"Convertido {arquivo_csv} para {arquivo_json}")
# Uso
csv_para_json('entrada.csv', 'saida.json')
JSON para CSV (achatamento de estruturas)
def json_para_csv(arquivo_json, arquivo_csv):
with open(arquivo_json, 'r', encoding='utf-8') as json_file:
dados = json.load(json_file)
if not dados:
return
# Achata estruturas aninhadas
dados_planos = []
for item in dados:
item_plano = {}
for chave, valor in item.items():
if isinstance(valor, (list, dict)):
item_plano[chave] = json.dumps(valor, ensure_ascii=False)
else:
item_plano[chave] = valor
dados_planos.append(item_plano)
with open(arquivo_csv, 'w', newline='', encoding='utf-8') as csv_file:
campos = dados_planos[0].keys()
escritor = csv.DictWriter(csv_file, fieldnames=campos)
escritor.writeheader()
escritor.writerows(dados_planos)
print(f"Convertido {arquivo_json} para {arquivo_csv}")
# Uso
json_para_csv('entrada.json', 'saida.csv')
Script completo de conversão bidirecional
def converter(formato_origem, arquivo_origem, arquivo_destino):
if formato_origem == 'csv':
csv_para_json(arquivo_origem, arquivo_destino)
elif formato_origem == 'json':
json_para_csv(arquivo_origem, arquivo_destino)
else:
print("Formato não suportado. Use 'csv' ou 'json'.")
# Exemplo de uso
converter('csv', 'dados.csv', 'dados.json')
converter('json', 'dados.json', 'dados_convertido.csv')
8. Boas Práticas e Performance
Trabalhando com arquivos grandes
# Leitura sob demanda (recomendado para arquivos grandes)
with open('grande.csv', 'r', encoding='utf-8') as arquivo:
leitor = csv.reader(arquivo)
next(leitor) # Pula cabeçalho
for linha in leitor:
processar_linha(linha) # Processa uma linha por vez
# Para JSON grande, use ijson (biblioteca externa)
# import ijson
# with open('grande.json', 'r', encoding='utf-8') as arquivo:
# for item in ijson.items(arquivo, 'item'):
# processar_item(item)
Codificação de caracteres
# Sempre especificar encoding
with open('dados.csv', 'r', encoding='utf-8') as arquivo:
leitor = csv.reader(arquivo)
# Para arquivos com acentos, ensure_ascii=False é essencial
with open('dados.json', 'w', encoding='utf-8') as arquivo:
json.dump(dados, arquivo, ensure_ascii=False, indent=2)
Uso de with open() para gerenciamento de contexto
# Garantia de fechamento automático do arquivo
with open('dados.csv', 'r', encoding='utf-8') as arquivo:
# Processamento aqui
pass # Arquivo é fechado automaticamente ao sair do bloco
# Equivalente sem with (não recomendado)
arquivo = open('dados.csv', 'r', encoding='utf-8')
try:
# Processamento
pass
finally:
arquivo.close()
Referências
- Documentação oficial do módulo csv — Referência completa para todas as funcionalidades do módulo csv, incluindo dialetos, formatação e exemplos avançados.
- Documentação oficial do módulo json — Guia completo para serialização e desserialização JSON, incluindo parâmetros avançados e codificadores personalizados.
- Real Python: Reading and Writing CSV Files in Python — Tutorial prático com exemplos detalhados de leitura e escrita de CSV, incluindo DictReader e tratamento de erros.
- Real Python: Working With JSON Data in Python — Guia completo sobre manipulação de JSON, desde operações básicas até conversão de objetos personalizados.
- Python for Data Analysis: CSV and JSON Processing — Documentação do pandas sobre processamento de CSV e JSON, útil para análises mais complexas com grandes volumes de dados.
- W3Schools: Python CSV Tutorial — Tutorial introdutório com exemplos práticos para iniciantes em manipulação de CSV.
- GeeksforGeeks: Working with CSV files in Python — Guia abrangente com exemplos de leitura, escrita e manipulação avançada de arquivos CSV.