CSV é mais simples do que parece (e mais complicado do que você esperaria)
Um arquivo CSV é só texto: linhas separadas por quebras de linha, campos separados por vírgulas. Essa é a ideia. Na prática, você esbarra em strings com aspas que contêm vírgulas, campos com quebras de linha embutidas, convenções regionais diferentes (vírgula vs ponto e vírgula), arquivos salvos do Excel que incluem um BOM — casos de borda suficientes para escrever seu próprio line.split(",") ser quase sempre erro.
O módulo embutido csv do Python cuida de tudo. Você raramente vai precisar de outra coisa para arquivos pequenos e médios.
Lendo um CSV com csv.reader
csv.reader produz cada linha como uma lista de strings:
import csv
with open("people.csv", newline="") as f:
reader = csv.reader(f)
for row in reader:
print(row)
Alguns detalhes não óbvios:
- Sempre passe
newline=""paraopen. O módulo csv cuida das quebras de linha; sem isso, você recebe linhas em branco extras no Windows. - Todo valor é string.
"42"continua sendo string até você chamarint(...)em cima. CSV não tem tipos. - A linha de cabeçalho é só mais uma linha. Se seu arquivo tem cabeçalhos, ou pule a primeira linha manualmente ou mude para
DictReader.
Pulando a linha de cabeçalho
import csv
with open("people.csv", newline="") as f:
reader = csv.reader(f)
headers = next(reader) # pulls the first row out
for row in reader:
print(row)
next(reader) avança o iterador por um e retorna aquela linha.
Lendo como dicts com DictReader
csv.DictReader trata a primeira linha como cabeçalhos e te dá cada linha subsequente como dict:
import csv
with open("people.csv", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["name"], row["email"])
Isso quase sempre é o que você quer. Nomes de coluna são autodocumentativos, e reordenar colunas no arquivo de origem não quebra seu código.
Se o arquivo não tem cabeçalhos, passe-os explicitamente com fieldnames=["name", "email", ...].
Escrevendo um CSV com csv.writer
csv.writer transforma linhas (listas) em linhas CSV:
import csv
rows = [
["name", "age", "city"],
["Rosa", 30, "Lisbon"],
["Ada", 36, "London"],
]
with open("out.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(rows)
writerow(row) escreve uma linha; writerows(rows) escreve um iterável inteiro de uma vez. Os dois colocam aspas em campos automaticamente quando contêm vírgulas, aspas ou quebras de linha — você não precisa pensar nisso.
Escrevendo dicts com DictWriter
Quando seus dados já estão em forma de dict, DictWriter pula o passo "converter para lista":
import csv
people = [
{"name": "Rosa", "age": 30, "city": "Lisbon"},
{"name": "Ada", "age": 36, "city": "London"},
]
with open("out.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["name", "age", "city"])
writer.writeheader()
writer.writerows(people)
O argumento fieldnames controla tanto o cabeçalho quanto a ordem das colunas. Chaves nos seus dicts que não estão em fieldnames são silenciosamente descartadas (ou você pode disparar com extrasaction="raise").
Delimitadores e aspas diferentes
Nem todo "CSV" usa vírgulas. Locais europeus muitas vezes usam ;, arquivos separados por tab usam \t, alguns sistemas usam |. Passe um argumento delimiter=:
import csv
with open("data.tsv", newline="") as f:
reader = csv.reader(f, delimiter="\t")
for row in reader:
print(row)
Para arquivos com regras de aspas incomuns, csv.register_dialect(...) permite configurar uma vez e reusar. Para a maioria dos arquivos, os padrões mais delimiter= bastam.
Encoding
Arquivos CSV são texto — têm encoding. UTF-8 é o padrão moderno; arquivos originados do Excel no Windows às vezes usam cp1252 ou incluem um BOM UTF-8. Seja explícito:
with open("data.csv", newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
...
Se você vê UnicodeDecodeError, o arquivo não é no encoding que você chutou. Tente utf-8-sig (lida com o BOM do Excel), cp1252 ou latin-1 como suspeitos comuns.
Transformando linhas CSV em tipos úteis
Como todo valor chega como string, parsear é com você:
(StringIO deixa a gente rodar o exemplo sem arquivo real — em código de verdade você usaria open(path).)
Para CSVs com tipos complicados (datas, números nullable, true/false com dez grafias diferentes), considere pandas — tem convenções para a maioria já embutidas.
Quando recorrer ao pandas
pandas.read_csv(path) retorna um DataFrame, que é a estrutura certa no momento em que você quer:
- Filtrar linhas:
df[df["active"] == True] - Agregar:
df.groupby("city")["age"].mean() - Juntar com outra tabela
- Escrever de volta com formatação simples
import pandas as pd
df = pd.read_csv("people.csv")
adults = df[df["age"] >= 18]
adults.to_csv("adults.csv", index=False)
Pandas é exagero para leituras pequenas e lineares — e é uma dependência pesada (pip-install num ambiente virtual). Mas para qualquer coisa com cara de dado, é a ferramenta que a maioria dos analistas Python procura.
Fazendo streaming de arquivos muito grandes
csv.reader já é preguiçoso — lê uma linha de cada vez. Mantenha assim iterando (não chamando list(reader) de antemão), e sua memória fica estável independente do tamanho do arquivo:
import csv
with open("huge.csv", newline="") as f:
reader = csv.DictReader(f)
error_count = 0
for row in reader:
if row["status"] == "error":
error_count += 1
print(f"Found {error_count} errors.")
Isso lida com um arquivo de 10 GB tão feliz quanto um de 10 KB, contanto que você não acumule as linhas numa lista.
Alguns hábitos
- Sempre passe
newline=""aoopenao ler ou escrever CSVs. - Use
DictReader/DictWritersempre que o arquivo tem cabeçalhos — mais legível do que índices inteiros. - Seja explícito sobre encoding, principalmente com arquivos do Excel ou fontes não inglesas.
- Converta tipos logo no passo da leitura para o código downstream não ter que fazer.
- Recorra ao pandas quando quiser analisar os dados, não só mover.
Na sequência
Agora você consegue ler JSON e CSV. A última habilidade do mundo real que vamos cobrir é buscar dados pela rede — esse é o próximo doc, sobre requisições HTTP com a biblioteca requests.
Perguntas frequentes
Como leio um arquivo CSV em Python?
Use o módulo embutido csv. csv.reader te dá cada linha como uma lista de strings; csv.DictReader usa a primeira linha como cabeçalhos e produz cada linha como dict. Abra o arquivo com newline='' para o Python não mexer nas quebras de linha: with open('data.csv', newline='') as f:.
Como escrevo um arquivo CSV em Python?
Combine csv.writer com um arquivo aberto em modo escrita e newline=''. Chame writer.writerow([...]) para cada linha ou writer.writerows([[...], [...]]) para um lote. Para dados baseados em dict, use csv.DictWriter — cuida dos cabeçalhos automaticamente.
Devo usar o módulo csv ou pandas?
Use csv para leituras e escritas rápidas, arquivos que você processa linha por linha e quando não quer outra dependência. Use pandas quando precisa filtrar, agrupar ou juntar — ou quando o arquivo é grande o suficiente para operações vetorizadas importarem. Lidam com os mesmos arquivos; a escolha é sobre o que você faz com os dados depois de carregar.
Por que meu CSV tem linhas em branco entre as linhas no Windows?
Você abriu o arquivo sem newline=''. O módulo csv escreve seus próprios terminadores de linha; sem esse argumento, o Python adiciona extras no Windows. Sempre abra arquivos CSV com open(path, newline='') tanto para leitura quanto para escrita.