W3docs

Arquivos CSV em Python

Aprenda a ler e escrever arquivos CSV em Python usando o módulo csv integrado, incluindo csv.reader, csv.writer, DictReader e DictWriter com exemplos práticos.

CSV (Comma-Separated Values, ou Valores Separados por Vírgula) é um dos formatos mais comuns para troca de dados tabulares — qualquer aplicativo de planilha, banco de dados e ferramenta de ciência de dados consegue ler e escrever esse formato. O módulo csv integrado ao Python cuida das partes complicadas automaticamente: colocar aspas em campos que contêm vírgulas, eliminar inconsistências de quebra de linha entre sistemas operacionais e mapear linhas para dicionários. Não é necessário instalar nada; o csv já vem em toda instalação Python.

Este capítulo aborda a leitura de arquivos CSV, a escrita de arquivos CSV, o trabalho com DictReader e DictWriter, o uso de delimitadores personalizados e os erros comuns a evitar.

O que é um Arquivo CSV?

Um arquivo CSV é um arquivo de texto simples em que cada linha representa uma linha de dados e cada campo dentro de uma linha é separado por um delimitador — geralmente uma vírgula. Veja um exemplo mínimo:

name,age,city
Alice,30,New York
Bob,25,London

A primeira linha geralmente é um cabeçalho que dá nome a cada coluna. As linhas seguintes contêm os dados propriamente ditos. Se o valor de um campo contiver uma vírgula, o campo é envolvido em aspas duplas:

name,bio
Alice,"Engineer, New York"

O módulo csv trata essas aspas de forma transparente, dispensando a necessidade de fazer o parsing manualmente.

Lendo Arquivos CSV com csv.reader

csv.reader transforma um arquivo aberto (ou qualquer iterável de strings) em um iterador que gera cada linha como uma lista Python.

Padrão básico — ler um arquivo CSV linha por linha

import csv

with open("people.csv", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

O argumento newline="" é importante. Sem ele, a tradução universal de quebras de linha do Python pode inserir linhas em branco extras no Windows, pois o módulo csv faz seu próprio tratamento de quebras de linha internamente.

Supondo que people.csv contenha os dados do exemplo acima, a saída é:

['name', 'age', 'city']
['Alice', '30', 'New York']
['Bob', '25', 'London']

Observe que todos os valores — incluindo o número 30 — retornam como strings. O módulo csv não infere tipos de dados; converta-os você mesmo quando necessário.

Ignorando a Linha de Cabeçalho

Quando você quer apenas as linhas de dados e não o cabeçalho, chame next() no reader uma vez para consumir a primeira linha:

Ignorar a linha de cabeçalho com next()

import csv

with open("people.csv", newline="") as f:
    reader = csv.reader(f)
    header = next(reader)          # consume and store the header
    print("Columns:", header)
    for row in reader:             # only data rows remain
        name, age, city = row
        print(f"{name} is {age} years old and lives in {city}.")

Saída:

Columns: ['name', 'age', 'city']
Alice is 30 years old and lives in New York.
Bob is 25 years old and lives in London.

Carregando Todas as Linhas em uma Lista

Se você precisar do arquivo inteiro na memória de uma vez, passe o reader para list():

import csv

with open("people.csv", newline="") as f:
    reader = csv.reader(f)
    rows = list(reader)

print(rows[0])   # header row
print(rows[1])   # first data row

Saída:

['name', 'age', 'city']
['Alice', '30', 'New York']

Escrevendo Arquivos CSV com csv.writer

csv.writer escreve linhas em qualquer objeto semelhante a um arquivo, colocando aspas automaticamente nos campos que contêm o delimitador, aspas duplas ou caracteres de quebra de linha.

Escrever linhas em um novo arquivo CSV

import csv

rows = [
    ["product", "price", "quantity"],
    ["Apple", 1.2, 50],
    ["Banana", 0.5, 100],
    ["Cherry", 3.0, 30],
]

with open("inventory.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

Após executar isso, inventory.csv contém:

product,price,quantity
Apple,1.2,50
Banana,0.5,100
Cherry,3.0,30

Use writer.writerow(row) para escrever uma única linha, ou writer.writerows(rows) para escrever várias de uma vez. Ambos aceitam qualquer iterável.

Por que newline="" é Importante ao Escrever

No Windows, Python abre arquivos de texto em um modo que traduz \n para \r\n. O módulo csv também escreve terminações de linha \r\n por padrão. Juntos, eles produzem \r\r\n — uma linha em branco entre cada linha quando o arquivo é aberto em outro programa. Passar newline="" suprime a tradução extra e deixa o csv gerenciar as terminações de linha por conta própria.

Lendo Arquivos CSV com csv.DictReader

DictReader mapeia cada linha para um OrderedDict (ou dict simples no Python 3.8+) indexado pelos nomes das colunas na linha de cabeçalho. Esta é a abordagem preferida quando as colunas têm nomes significativos e você quer acessá-las pelo nome em vez de pelo índice.

Ler um arquivo CSV como uma sequência de dicionários

import csv

with open("people.csv", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row["name"], "—", row["city"])

Saída:

Alice — New York
Bob — London

DictReader lê automaticamente a primeira linha como cabeçalho. Você pode substituir esse comportamento passando um argumento fieldnames:

import csv

# File has no header; provide field names explicitly
with open("data_no_header.csv", newline="") as f:
    reader = csv.DictReader(f, fieldnames=["name", "age", "city"])
    for row in reader:
        print(row)

O atributo reader.fieldnames sempre contém a lista de nomes de colunas em uso, o que é útil para inspeção antes de processar as linhas.

Escrevendo Arquivos CSV com csv.DictWriter

DictWriter é o par correspondente ao DictReader. Você fornece os nomes das colunas com antecedência e, em seguida, escreve dicionários — o writer mapeia cada chave para a coluna correta.

Escrever uma lista de dicionários em um arquivo CSV

import csv

people = [
    {"name": "Alice", "age": 30, "city": "New York"},
    {"name": "Bob", "age": 25, "city": "London"},
]

fieldnames = ["name", "age", "city"]

with open("people_out.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()          # writes the column-name row
    writer.writerows(people)

O arquivo resultante:

name,age,city
Alice,30,New York
Bob,25,London

writeheader() usa a lista fieldnames fornecida na construção. Chame-o uma vez antes de qualquer chamada a writerow().

Tratando Chaves Extras ou Ausentes

Por padrão, DictWriter lança um ValueError se um dicionário contém uma chave que não está em fieldnames. Você pode alterar esse comportamento com o parâmetro extrasaction:

writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")

Por outro lado, se um dicionário não tiver uma chave, o writer escreve uma string vazia para aquele campo, a menos que você forneça um padrão em restval:

writer = csv.DictWriter(f, fieldnames=fieldnames, restval="N/A")

Delimitadores e Citação Personalizados

Arquivos CSV do mundo real nem sempre são delimitados por vírgulas. Arquivos com valores separados por tabulação (TSV) e arquivos delimitados por pipe são comuns. Use o parâmetro delimiter para lidar com eles:

Ler um arquivo separado por tabulação

import csv

with open("scores.tsv", newline="") as f:
    reader = csv.reader(f, delimiter="\t")
    for row in reader:
        print(row)

Escrever um arquivo delimitado por pipe

import csv

with open("output.psv", "w", newline="") as f:
    writer = csv.writer(f, delimiter="|")
    writer.writerow(["id", "name", "score"])
    writer.writerow([1, "Alice", 98])
    writer.writerow([2, "Bob", 87])

Arquivo de saída:

id|name|score
1|Alice|98
2|Bob|87

Constantes de Citação

O parâmetro quoting controla quais campos são colocados entre aspas na saída:

ConstanteValorComportamento
csv.QUOTE_MINIMAL0Coloca aspas apenas em campos que contêm o delimitador, quotechar ou uma quebra de linha (padrão)
csv.QUOTE_ALL1Coloca aspas em todos os campos
csv.QUOTE_NONNUMERIC2Coloca aspas em todos os campos não numéricos; o reader converte campos sem aspas para float
csv.QUOTE_NONE3Nunca coloca aspas; lança erro se o delimitador aparecer em um campo

Forçar aspas em todos os campos

import csv, io

output = io.StringIO()
writer = csv.writer(output, quoting=csv.QUOTE_ALL)
writer.writerow(["name", "bio"])
writer.writerow(["Alice", "Engineer, New York"])
print(output.getvalue())

Saída:

"name","bio"
"Alice","Engineer, New York"

Usando io.StringIO para CSV em Memória

Quando você não precisa acessar o sistema de arquivos — por exemplo, em testes ou ao processar dados CSV recebidos de uma API — use io.StringIO como objeto semelhante a um arquivo:

Analisar CSV a partir de uma string

import csv
import io

raw = "name,score\nAlice,95\nBob,87\n"

reader = csv.DictReader(io.StringIO(raw))
for row in reader:
    print(row["name"], "scored", row["score"])

Saída:

Alice scored 95
Bob scored 87

Erros Comuns

Todos os Valores São Strings

csv.reader e DictReader sempre retornam strings. Converta os valores explicitamente:

age = int(row["age"])
price = float(row["price"])

Problemas de Codificação

Abra os arquivos com a codificação correta para evitar UnicodeDecodeError. UTF-8 é a codificação mais comum para arquivos CSV modernos, mas arquivos exportados do Excel podem usar latin-1 ou cp1252:

with open("data.csv", newline="", encoding="utf-8") as f:
    reader = csv.reader(f)

Linhas em Branco

Se o seu arquivo CSV contiver linhas em branco entre as linhas de dados, csv.reader gera listas vazias [] para elas. Filtre-as:

import csv

with open("data.csv", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        if not row:        # skip blank lines
            continue
        print(row)

Tratamento de Erros

Envolva as operações com arquivos em um bloco try/except para lidar com arquivos ausentes e erros de permissão de forma adequada:

import csv

try:
    with open("data.csv", newline="") as f:
        reader = csv.reader(f)
        for row in reader:
            print(row)
except FileNotFoundError:
    print("Error: data.csv was not found.")
except PermissionError:
    print("Error: no permission to read data.csv.")

csv vs Pandas para Arquivos Grandes

O módulo csv é ideal para:

  • Arquivos pequenos a médios (até algumas centenas de MB)
  • Scripts que não têm o Pandas instalado
  • Situações em que você precisa de controle refinado sobre leitura e escrita

Para conjuntos de dados grandes, filtragens complexas ou operações de agregação, a biblioteca de terceiros pandas fornece pd.read_csv() e DataFrame.to_csv(), que são significativamente mais rápidos e ricos em recursos.

Juntando Tudo

O exemplo a seguir lê um arquivo CSV, filtra linhas com base em uma condição e escreve os resultados filtrados em um novo arquivo:

Filtrar linhas e escrever um novo arquivo CSV

import csv

input_file = "inventory.csv"
output_file = "expensive.csv"

with open(input_file, newline="") as infile, \
     open(output_file, "w", newline="") as outfile:

    reader = csv.DictReader(infile)
    writer = csv.DictWriter(outfile, fieldnames=reader.fieldnames)

    writer.writeheader()
    for row in reader:
        if float(row["price"]) >= 1.0:
            writer.writerow(row)

print(f"Filtered rows written to {output_file}.")

Esse padrão — abrir ambos os arquivos no mesmo bloco with, transmitir linhas do reader para o writer — lida com arquivos de qualquer tamanho sem carregar tudo na memória de uma vez.

Capítulos Relacionados

Prática

Prática
Which csv module class maps each CSV row to a dictionary keyed by column names?
Which csv module class maps each CSV row to a dictionary keyed by column names?
Was this page helpful?