---
title: "Ler e Escrever Arquivos CSV em Python com o Módulo csv"
url: "https://python.dev.br/blog/python-csv-leitura-escrita-arquivos/"
markdown_url: "https://python.dev.br/blog/python-csv-leitura-escrita-arquivos.MD"
description: "Aprenda a ler e escrever arquivos CSV em Python com o módulo csv da biblioteca padrão: reader, DictReader, DictWriter, dialetos, encoding, ponto-e-vírgula e vírgula decimal no padrão brasileiro, arquivos grandes e quando migrar para o pandas. Guia prático em português."
date: "2026-07-11"
author: "Equipe Python Brasil"
---

# Ler e Escrever Arquivos CSV em Python com o Módulo csv

Aprenda a ler e escrever arquivos CSV em Python com o módulo csv da biblioteca padrão: reader, DictReader, DictWriter, dialetos, encoding, ponto-e-vírgula e vírgula decimal no padrão brasileiro, arquivos grandes e quando migrar para o pandas. Guia prático em português.


O CSV (*Comma-Separated Values*) é, disparado, o formato de dados mais usado no dia a dia de quem programa em Python no Brasil. Exportação de extrato bancário, relatório de vendas do ERP, base de CEPs do Correios, planilha de clientes do CRM, arquivo de [dados abertos do governo](https://dados.gov.br/) — tudo chega como CSV. A boa notícia é que o Python já traz um módulo dedicado e robusto para ler e escrever esse formato: o `csv`, da biblioteca padrão. Neste tutorial você vai aprender a usá-lo com exemplos práticos voltados para a realidade brasileira, incluindo os dois problemas que mais atrapalham por aqui — o **ponto-e-vírgula como separador** e o **encoding de arquivos legados**.

Se você já automatiza [planilhas Excel com Python](/blog/python-e-excel-openpyxl/) ou [gera relatórios em PDF](/blog/python-gerar-pdf-relatorios/), dominar o CSV fecha um ciclo essencial de automação de escritório. Para quem está começando, vale revisar o [guia de Python para iniciantes](/blog/python-para-iniciantes-guia-completo/) e o de [manipulação de arquivos](/blog/manipulacao-de-arquivos-python/); aqui o foco é um formato específico, mas onipresente.

## Por que não usar só `str.split(",")`

A tentação, ao ver a primeira linha de um CSV, é separar os campos com `"campo1,campo2".split(",")`. Isso funciona para o caso mais simples — mas quebra rápido. Considere uma linha de venda:

```text
"Notebook Dell, 16GB",1,"R$ 4.500,00"
```

O campo do produto contém uma vírgula dentro de aspas. Um `split(",")` ingênuo devolve quatro pedaços em vez de três, corrompendo a linha. O módulo `csv` entende as regras do formato — aspas, vírgulas dentro de campos, quebras de linha embutidas — e faz o trabalho corretamente. **Use sempre o módulo `csv` em vez de `split`.**

## Lendo CSV: `reader` e `DictReader`

O fluxo de leitura é sempre o mesmo: abrir o arquivo, criar o leitor, iterar. Para um arquivo `vendas.csv` em UTF-8 com vírgula como separador:

```python
import csv

with open("vendas.csv", "r", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)
    cabecalho = next(leitor)          # consome a primeira linha
    for linha in leitor:              # cada linha é uma lista de strings
        print(linha[0], linha[1])
```

O `csv.reader` devolve cada registro como uma **lista** de strings, acessível por índice. Quando o arquivo tem cabeçalho, é mais legível usar o `csv.DictReader`, que transforma cada linha em um **dicionário** usando os nomes das colunas como chaves:

```python
with open("vendas.csv", "r", encoding="utf-8") as arquivo:
    leitor = csv.DictReader(arquivo)
    for registro in leitor:
        print(registro["produto"], registro["valor"])
```

O `DictReader` é mais robusto a mudanças na ordem das colunas e deixa o código autodocumentado. Para uma referência rápida do conceito, veja a entrada do [glossário sobre CSV](/glossario/csv/).

## Escrevendo CSV: `writer` e `DictWriter`

Para gravar, use `csv.writer` com listas ou `csv.DictWriter` com dicionários. **Atenção ao detalhe que mais custa tempo no Windows:** sempre abra o arquivo para escrita com `newline=""`.

```python
import csv

registros = [
    {"produto": "Notebook Dell, 16GB", "qtd": 1, "valor": 4500.00},
    {"produto": "Mouse sem fio",        "qtd": 3, "valor": 89.90},
    {"produto": "Teclado mecânico",     "qtd": 2, "valor": 259.00},
]

with open("saida.csv", "w", encoding="utf-8", newline="") as arquivo:
    colunas = ["produto", "qtd", "valor"]
    escritor = csv.DictWriter(arquivo, fieldnames=colunas)
    escritor.writeheader()
    escritor.writerows(registros)
```

O `newline=""` impede que o Python traduza o caractere de nova linha no Windows — sem ele, o módulo `csv` adiciona a sua própria quebra e o arquivo fica com linhas em branco duplicadas. Sem `newline=""`, o mesmo arquivo que abre perfeitamente no Linux aparece "pulando" uma linha a cada registro no Excel.

## O cenário brasileiro: ponto-e-vírgula e vírgula decimal

Aqui está a pegadinha mais comum para quem trabalha com dados no Brasil. Como usamos a **vírgula como separador decimal** (`R$ 4.500,00`), o Excel em português não pode usar a vírgula também como separador de campos. Ele usa, então, o **ponto-e-vírgula**. Resultado: a maior parte dos CSVs brasileiros não é separada por vírgula, e sim por `;`.

Para ler um arquivo gerado pelo Excel brasileiro, informe o delimitador:

```python
with open("vendas_br.csv", "r", encoding="utf-8") as arquivo:
    leitor = csv.DictReader(arquivo, delimiter=";")
    for registro in leitor:
        # atenção: "valor" vem como "4500,00" (string com vírgula decimal)
        valor = float(registro["valor"].replace(".", "").replace(",", "."))
        print(registro["produto"], valor)
```

Repare na conversão do valor: como a vírgula é o decimal, é preciso remover o ponto de milhar e trocar a vírgula por ponto antes de chamar `float()`. Esse passo é a fonte número um de bugs em pipelines de dados brasileiros.

## Dialetos: quando o formato se repete

Se você lê e escreve vários arquivos no mesmo padrão, registre um **dialeto** em vez de repetir `delimiter=";"` em todo lugar:

```python
csv.register_dialect(
    "excel_br",
    delimiter=";",
    quotechar='"',
    quoting=csv.QUOTE_MINIMAL,
)

with open("vendas_br.csv", "r", encoding="utf-8") as arquivo:
    leitor = csv.DictReader(arquivo, dialect="excel_br")
    for registro in leitor:
        ...
```

O módulo já traz dialetos prontos, como `excel` (vírgula) e `excel-tab` (tabulação). Veja os disponíveis com `csv.list_dialects()`.

## Encoding: UTF-8, latin-1 e cp1252

O segundo problema mais frequente é o `UnicodeDecodeError` ao ler um arquivo com acentos. Arquivos modernos costumam vir em UTF-8, mas sistemas legados brasileiros — ERPs antigos, exports de mainframe, planilhas salvas no Windows em empresas que não padronizaram o encoding — frequentemente usam **latin-1** (ISO-8859-1) ou **cp1252** (Windows-1252). Se você não conhece a origem, uma estratégia robusta é tentar UTF-8 e recuar:

```python
def ler_csv(caminho: str) -> list[dict]:
    for encoding in ("utf-8", "latin-1", "cp1252"):
        try:
            with open(caminho, "r", encoding=encoding, newline="") as arquivo:
                return list(csv.DictReader(arquivo))
        except UnicodeDecodeError:
            continue
    raise ValueError(f"Não foi possível ler {caminho} com nenhum encoding")
```

Ao **escrever** CSVs, padronize em UTF-8 — é o formato mais portável e o que o pandas, o Google Sheets e a maioria das ferramentas modernas esperam.

## Arquivos grandes: processe linha por linha

Arquivos de dados públicos brasileiros podem ser enormes — a base do CNPJ, os dados do CAGED ou os microdados do IBGE costumam ter milhões de linhas. A vantagem do módulo `csv` é que ele é um **iterador preguiçoso**: lê uma linha por vez, sem carregar tudo na memória.

```python
total = 0.0
contador = 0

with open("caged.csv", "r", encoding="latin-1", newline="") as arquivo:
    leitor = csv.DictReader(arquivo, delimiter=";")
    for registro in leitor:
        salario = float(registro["salario"].replace(",", "."))
        total += salario
        contador += 1

print(f"Média salarial: R$ {total / contador:,.2f}")
```

Aqui está a diferença importante: chamar `list(leitor)` carrega o arquivo inteiro na memória (rápido, mas inviável para arquivos de vários gigabytes). Iterar diretamente com o `for` mantém o consumo de memória constante. Para análises que envolvem filtragem, agrupamento e estatísticas, vale migrar para o [pandas](/blog/introducao-ao-pandas/), que lida com tipos, datas e operações vetorizadas de forma muito mais expressiva.

## Quando migrar para o pandas

O módulo `csv` é a ferramenta certa para **transformar, filtrar e reescrever** arquivos texto, e para pipelines em que você quer controle total e baixo consumo de memória. Quando o trabalho passa a ser **analisar** os dados — calcular médias, cruzar tabelas, fazer gráficos, tratar datas —, o pandas encurta o caminho:

```python
import pandas as pd

# lê CSV brasileiro (ponto-e-vírgula e vírgula decimal) de uma vez
df = pd.read_csv("vendas_br.csv", sep=";", decimal=",", encoding="utf-8")
print(df["valor"].sum())
```

Repare como o pandas trata o `decimal=","` nativamente, sem a conversão manual. Para comparações de performance e quando considerar alternativas modernas, veja também nosso artigo sobre o [Polars](/blog/polars-alternativa-pandas-python/). E se os dados precisam trafegar entre sistemas com estrutura hierárquica, o [JSON](/blog/trabalhando-com-json-python/) costuma ser uma escolha melhor que o CSV.

## Boas práticas que evalam horas de debug

- Sempre passe `encoding="utf-8"` ao abrir; recorra a `latin-1`/`cp1252` só quando a origem for legada.
- Use `newline=""` ao escrever — no Windows isso evita linhas duplicadas.
- Desconfie do delimitador: no Brasil, `;` é mais comum que `,`.
- Converta números tratando a vírgula decimal antes de chamar `float()`.
- Para arquivos grandes, itere — não chame `list()` sobre o leitor inteiro.
- Valide dados externos: campos ausentes viram `None` no `DictReader`, e use o parâmetro `restval` para definir um valor padrão.

Com o módulo `csv` dominado, você fecha a base de toda automação de dados em Python: ler a entrada tabular mais universal do mundo corporativo brasileiro, transformá-la e gerar saídas confiáveis — sejam elas outros CSVs, [planilhas Excel](/blog/python-e-excel-openpyxl/) ou relatórios em [PDF](/blog/python-gerar-pdf-relatorios/) e [Word](/blog/python-e-word-python-docx/).
