Python CSV

A professora da escola do bairro mandou para a Ana as notas da turma numa planilha. A lojinha exporta o estoque do sistema de vendas. O banco deixa baixar o extrato. Os três chegam no mesmo formato: um arquivo CSV, a maneira mais simples e mais comum de guardar uma tabela num arquivo de texto. Nesta aula você aprende a ler e gravar esses arquivos com o módulo csv do Python, inclusive os que saem do Excel em português, que têm um jeitinho próprio.

Você vai aprender
  • O que tem dentro de um arquivo CSV.
  • A ler as linhas como listas com csv.reader e pular o cabeçalho com next().
  • Que tudo o que vem do CSV é texto, e como converter para número.
  • A gravar com csv.writer, writerow e writerows.
  • Por que sempre abrir com newline="".
  • A ler cada linha como um dicionário com DictReader e gravar com DictWriter.
  • O CSV do Excel brasileiro: ponto e vírgula (delimiter=";"), vírgula decimal e o utf-8-sig.
  • Os erros reais: KeyError, ValueError, arquivo fechado, leitor que "secou".

A ideia: uma tabela escrita em texto

Pense na tabela de notas no caderno da professora: cada linha é um aluno, cada coluna é uma informação (nome, turma, nota), e a primeira linha diz o nome de cada coluna. Para guardar isso num arquivo de texto simples, basta uma regra: uma linha da tabela por linha do arquivo, e uma vírgula entre uma coluna e outra. É isso que quer dizer CSV: Comma-Separated Values, "valores separados por vírgula".

nometurmanota
BiaA8.5
CaioB6.0
DudaA9.5
EnzoB7.0

A mesma tabela, como arquivo notas.csv, vista com o cat do terminal:

$ cat notas.csv
nome,turma,nota
Bia,A,8.5
Caio,B,6.0
Duda,A,9.5
Enzo,B,7.0

É só texto: dá para abrir no editor de textos, no Excel, no LibreOffice Calc ou no Google Planilhas. A primeira linha é o cabeçalho (os nomes das colunas); as outras são os dados.

Você poderia ler esse arquivo com o que já sabe (open, um for e split(",")). Mas o CSV tem casos chatos, como um nome que tem vírgula dentro, e o módulo csv, que já vem com o Python, resolve todos eles. A seção Formas diferentes mostra o split quebrando.


1. Lendo: csv.reader

import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)
    for linha in leitor:
        print(linha)
$ python3 ler1.py
['nome', 'turma', 'nota']
['Bia', 'A', '8.5']
['Caio', 'B', '6.0']
['Duda', 'A', '9.5']
['Enzo', 'B', '7.0']
import csv
Traz o módulo csv, que já vem com o Python (não precisa instalar nada).
open("notas.csv", newline="", encoding="utf-8")
Abre o arquivo para leitura, como na aula Abrindo Arquivos. A novidade é o newline="": ele deixa o módulo csv cuidar sozinho das quebras de linha (a seção 4 explica o porquê).
csv.reader(arquivo)
Cria um leitor (reader) de CSV em cima do arquivo aberto.
for linha in leitor:
A cada volta, o leitor entrega uma linha do arquivo já separada: uma lista com uma posição para cada coluna.

O cabeçalho veio junto, como se fosse um aluno chamado "nome". Quase sempre você quer separá-lo dos dados. O jeito é pedir a primeira linha ao leitor com next() ("próximo") antes do for:

import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)
    cabecalho = next(leitor)
    print("Colunas:", cabecalho)
    soma = 0
    quantos = 0
    for nome, turma, nota in leitor:
        print(f"{nome} (turma {turma}): {nota}")
        soma = soma + float(nota)
        quantos = quantos + 1

print(f"Média da turma: {soma / quantos:.2f}")
$ python3 ler2.py
Colunas: ['nome', 'turma', 'nota']
Bia (turma A): 8.5
Caio (turma B): 6.0
Duda (turma A): 9.5
Enzo (turma B): 7.0
Média da turma: 7.75
cabecalho = next(leitor)
Tira a primeira linha do leitor e guarda. O for que vem depois continua de onde o next parou: começa no Bia.
for nome, turma, nota in leitor:
Cada linha é uma lista de 3 itens, e o desempacotamento dá um nome a cada um.
float(nota)
Converte o texto "8.5" em número para poder somar. Veja abaixo por quê.

Tudo o que vem do CSV é texto

O arquivo é texto puro, e o leitor não tenta adivinhar o que é número: toda coluna chega como str. Olhe:

import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)
    next(leitor)
    primeira = next(leitor)

print(primeira)
print(type(primeira[2]))
print(primeira[2] + 1)
$ python3 tipo.py
['Bia', 'A', '8.5']
<class 'str'>
Traceback (most recent call last):
  File "/home/ana/tipo.py", line 10, in <module>
    print(primeira[2] + 1)
          ~~~~~~~~~~~~^~~
TypeError: can only concatenate str (not "int") to str

A nota é o texto '8.5' (repare nas aspas na lista), e somar texto com número dá TypeError: "só dá para concatenar (juntar) str com str, não com int". Sempre converta: float(...) para números com casas decimais, int(...) para inteiros (aula Conversão de Tipos).

Missão: a caixa tem duas abas, o programa e o notas.csv. Faça o programa mostrar uma frase por aluno, como Bia tirou 8.5, sem mostrar a linha do cabeçalho (nada de nome tirou nota).

import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)
    for linha in leitor:
        print(linha)
nome,turma,nota
Bia,A,8.5
Caio,B,6.0
Duda,A,9.5
Enzo,B,7.0
import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)
    next(leitor)
    for nome, turma, nota in leitor:
        print(f"{nome} tirou {nota}")

2. Gravando: csv.writer

O caminho de volta: você tem os dados numa lista de listas e quer um .csv para abrir na planilha.

import csv

produtos = [
    ["produto", "preco", "estoque"],
    ["café", "18.90", "12"],
    ["pão de queijo", "2.50", "40"],
    ["açúcar", "5.99", "0"],
]

with open("estoque.csv", "w", newline="", encoding="utf-8") as arquivo:
    escritor = csv.writer(arquivo)
    escritor.writerow(produtos[0])
    escritor.writerows(produtos[1:])

print("Gravei estoque.csv")
$ python3 escrever1.py
Gravei estoque.csv
$ cat estoque.csv
produto,preco,estoque
café,18.90,12
pão de queijo,2.50,40
açúcar,5.99,0
open("estoque.csv", "w", newline="", …)
Abre para escrita ("w": cria o arquivo ou apaga o que havia). Mais uma vez, newline="".
csv.writer(arquivo)
Cria um escritor (writer) de CSV.
escritor.writerow(lista)
"Escreva uma linha" (write row): junta os itens com vírgulas e acrescenta a quebra de linha.
escritor.writerows(lista_de_listas)
"Escreva as linhas": o mesmo, para várias linhas de uma vez.

Os itens não precisam ser textos: writerow(["café", 18.9, 12]) também funciona, e o escritor transforma cada um em texto (o 18.9 sai como 18.9, sem o zero do fim; se a aparência importar, formate antes: f"{preco:.2f}").

As aspas que aparecem sozinhas

E se um valor tiver uma vírgula dentro? Um cliente cadastrado como "Silva, Ana" quebraria a regra "vírgula separa colunas". O escritor resolve: põe o valor entre aspas duplas. Se o valor tiver aspas, ele as dobra.

import csv

clientes = [
    ["nome", "cidade"],
    ["Silva, Ana", "Teresina"],
    ['Bia "Baixinha" Costa', "Recife"],
]

with open("clientes.csv", "w", newline="", encoding="utf-8") as arquivo:
    csv.writer(arquivo).writerows(clientes)

with open("clientes.csv", newline="", encoding="utf-8") as arquivo:
    for linha in csv.reader(arquivo):
        print(linha)
$ python3 aspas.py
['nome', 'cidade']
['Silva, Ana', 'Teresina']
['Bia "Baixinha" Costa', 'Recife']
$ cat clientes.csv
nome,cidade
"Silva, Ana",Teresina
"Bia ""Baixinha"" Costa",Recife

Dentro do arquivo, "Silva, Ana" ficou entre aspas, e as aspas do apelido viraram "". Na hora de ler, o csv.reader desfaz tudo e devolve os valores originais. Você não precisa pensar nisso: é exatamente para essas coisas que o módulo existe.


3. Cada linha como dicionário: DictReader

Com o reader, você lembra que a nota é a posição [2]. Se um dia a professora acrescentar uma coluna no meio, o programa passa a ler a coluna errada. O csv.DictReader usa o cabeçalho para dar nome a cada valor: cada linha vira um dicionário.

import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    for aluno in csv.DictReader(arquivo):
        print(aluno)
        print("  ->", aluno["nome"], "tirou", aluno["nota"])
$ python3 dict1.py
{'nome': 'Bia', 'turma': 'A', 'nota': '8.5'}
  -> Bia tirou 8.5
{'nome': 'Caio', 'turma': 'B', 'nota': '6.0'}
  -> Caio tirou 6.0
{'nome': 'Duda', 'turma': 'A', 'nota': '9.5'}
  -> Duda tirou 9.5
{'nome': 'Enzo', 'turma': 'B', 'nota': '7.0'}
  -> Enzo tirou 7.0
csv.DictReader(arquivo)
Um leitor que usa a primeira linha como as chaves. Não precisa de next(): o cabeçalho já foi consumido e não aparece como dado.
aluno["nota"]
O valor pelo nome da coluna, e não pela posição. Continua sendo texto: float(aluno["nota"]) para fazer contas.

Gravando dicionários: DictWriter

import csv

pedidos = [
    {"cliente": "Bia", "produto": "café", "quantidade": 2},
    {"cliente": "Caio", "produto": "pão de queijo", "quantidade": 10},
]

with open("pedidos.csv", "w", newline="", encoding="utf-8") as arquivo:
    escritor = csv.DictWriter(arquivo, fieldnames=["cliente", "produto", "quantidade"])
    escritor.writeheader()
    escritor.writerows(pedidos)

print("Gravei pedidos.csv")
$ python3 dict2.py
Gravei pedidos.csv
$ cat pedidos.csv
cliente,produto,quantidade
Bia,café,2
Caio,pão de queijo,10
fieldnames=[…]
Os nomes das colunas (field names, "nomes dos campos"), na ordem em que vão aparecer no arquivo. É obrigatório: o escritor precisa saber quais chaves procurar em cada dicionário.
escritor.writeheader()
"Escreva o cabeçalho": grava a linha com os nomes das colunas. Sem ela, o arquivo sai só com os dados.
escritor.writerows(pedidos)
Grava um dicionário por linha (para um só, writerow).

4. Por que newline=""?

Todos os open desta aula têm newline="". É a recomendação da documentação oficial do módulo csv, e o motivo aparece quando se olha o arquivo gravado com cat -A, que mostra os caracteres invisíveis:

$ head -n 1 estoque.csv | cat -A
produto,preco,estoque^M$

O $ é o fim da linha, e o ^M antes dele é um caractere a mais, o \r ("retorno de carro"). O escritor de CSV termina cada linha com \r\n, que é o que o padrão do CSV pede e o que o Excel espera. Ou seja: o módulo csv já cuida das quebras de linha sozinho. O newline="" diz ao open: "não mexa nelas, deixe passar como estão".

Sem ele, o open também tenta "ajudar" com as quebras de linha, e os dois ajudando ao mesmo tempo atrapalham:

  • No Windows, gravando: o open troca cada \n por \r\n, e o fim de linha vira \r\r\n. No Excel, aparece uma linha em branco entre cada linha. (No Linux da Ana o open não faz essa troca, por isso o erro não aparece aqui; mas o seu programa pode rodar no Windows de alguém.)
  • Em qualquer sistema, lendo: um valor entre aspas pode ter uma quebra de linha dentro (um endereço em duas linhas, por exemplo). Sem newline="", o open altera essa quebra antes de o leitor ver.
A regra para guardar

Abriu um arquivo para usar com o módulo csv? Escreva newline="" e encoding="utf-8". Sempre, lendo ou gravando.


5. O CSV do Excel brasileiro: ponto e vírgula

No Brasil, a vírgula já tem dono: é a vírgula decimal (8,5). Por isso o Excel e o LibreOffice em português, quando salvam um CSV, separam as colunas com ponto e vírgula. A mesma tabela de notas, salva pela professora no Excel, chega assim:

$ cat notas_excel.csv
nome;turma;nota
Bia;A;8,5
Caio;B;6,0
Duda;A;9,5
Enzo;B;7,0

Duas diferenças: o separador é ; e as notas têm vírgula. Para o separador, todo leitor e escritor do módulo aceita a opção delimiter ("delimitador", o caractere que separa as colunas). Para a vírgula decimal, troque por ponto antes de converter:

import csv

with open("notas_excel.csv", newline="", encoding="utf-8") as arquivo:
    alunos = list(csv.DictReader(arquivo, delimiter=";"))

soma = 0
for aluno in alunos:
    nota = float(aluno["nota"].replace(",", "."))
    print(f"{aluno['nome']}: {nota}")
    soma = soma + nota

media = soma / len(alunos)
print(f"Média: {media:.2f}".replace(".", ","))
$ python3 excel.py
Bia: 8.5
Caio: 6.0
Duda: 9.5
Enzo: 7.0
Média: 7,75
delimiter=";"
"As colunas estão separadas por ponto e vírgula." Vale também para csv.reader, csv.writer e csv.DictWriter.
list(csv.DictReader(…))
Lê todas as linhas de uma vez numa lista, para poder usar depois de fechar o arquivo (e saber quantos alunos são com len).
aluno["nota"].replace(",", ".")
Troca a vírgula decimal pelo ponto: "8,5" vira "8.5", que o float entende.
.replace(".", ",")
No fim, o caminho de volta: mostra a média no jeito brasileiro.

Os acentos e o utf-8-sig

Quando a professora escolhe no Excel "CSV UTF-8", o arquivo ganha três bytes invisíveis bem no começo, chamados BOM (byte order mark, uma "marca" que avisa que o arquivo é UTF-8). Lido com encoding="utf-8", o BOM gruda no nome da primeira coluna, e aluno["nome"] não acha nada (veja em Quando dá errado). A solução é a codificação "utf-8-sig", que é o UTF-8 que sabe pular o BOM se ele existir (e lê normalmente se não existir):

import csv

with open("notas_bom.csv", newline="", encoding="utf-8-sig") as arquivo:
    for aluno in csv.DictReader(arquivo, delimiter=";"):
        print(aluno["nome"], aluno["nota"])
$ python3 bom2.py
Bia 8,5
Caio 6,0

E no caminho contrário, para gravar um CSV que o Excel em português abra com as colunas separadas e os acentos certos, use o ponto e vírgula e grave com o BOM:

import csv

with open("para_excel.csv", "w", newline="", encoding="utf-8-sig") as arquivo:
    escritor = csv.writer(arquivo, delimiter=";")
    escritor.writerow(["produto", "preço"])
    escritor.writerow(["café", "18,90"])

print("Gravei para_excel.csv")
$ python3 grava_excel.py
Gravei para_excel.csv
$ file para_excel.csv                   « o comando file descreve o arquivo
para_excel.csv: Unicode text, UTF-8 (with BOM) text, with CRLF line terminators

O file confirmou: UTF-8 com BOM, e linhas terminadas em \r\n (CRLF), como o Excel gosta.

Missão: o arquivo veio do Excel brasileiro. Do jeito que está, o programa quebra. Rode, leia o erro e conserte: ele deve mostrar Maior nota: 9.5. (Duas coisas para arrumar: o separador e a vírgula decimal.)

import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    alunos = list(csv.DictReader(arquivo))

maior = 0
for aluno in alunos:
    nota = float(aluno["nota"])
    if nota > maior:
        maior = nota

print("Maior nota:", maior)
nome;turma;nota
Bia;A;8,5
Caio;B;6,0
Duda;A;9,5
Enzo;B;7,0
import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    alunos = list(csv.DictReader(arquivo, delimiter=";"))

maior = 0
for aluno in alunos:
    nota = float(aluno["nota"].replace(",", "."))
    if nota > maior:
        maior = nota

print("Maior nota:", maior)

Formas diferentes de ler um CSV

Por que não usar só o que você já sabia, split(",")? Para o notas.csv funcionaria. Agora tente com o clientes.csv da seção 2, o do "Silva, Ana":

with open("clientes.csv", encoding="utf-8") as arquivo:
    for linha in arquivo:
        print(linha.strip().split(","))
$ python3 split.py
['nome', 'cidade']
['"Silva', ' Ana"', 'Teresina']
['"Bia ""Baixinha"" Costa"', 'Recife']

O split não conhece as aspas: cortou "Silva, Ana" em dois pedaços, e a linha ficou com três colunas. O apelido da Bia veio com as aspas dobradas do arquivo. O csv.reader, na seção 2, devolveu tudo certo.

FormaCada linha viraQuando usar
csv.readerLista: ['Bia', 'A', '8.5']Arquivos sem cabeçalho, ou quando você quer as colunas pela posição
csv.DictReaderDicionário: {'nome': 'Bia', …}Quase sempre, quando há cabeçalho: o código fica legível e não quebra se as colunas mudarem de lugar
linha.split(",")ListaSó para arquivos que você controla e que nunca têm vírgula nem aspas nos valores. Na dúvida, use o csv
Para gravarVocê entregaQuando usar
csv.writer + writerowListasOs dados já estão em listas
csv.DictWriter + writeheader + writerowDicionáriosOs dados estão em dicionários (o caso do JSON, por exemplo)

Quando dá errado

CSV do Excel lido sem delimiter=";": KeyError
import csv

with open("notas_excel.csv", newline="", encoding="utf-8") as arquivo:
    for aluno in csv.DictReader(arquivo):
        print(aluno)
        print(aluno["nota"])
$ python3 excel_sem.py
{'nome;turma;nota': 'Bia;A;8', None: ['5']}
Traceback (most recent call last):
  File "/home/ana/excel_sem.py", line 6, in <module>
    print(aluno["nota"])
          ~~~~~^^^^^^^^
KeyError: 'nota'

O print(aluno) da linha 5 conta a história toda. Procurando vírgulas, o leitor achou uma só: a do 8,5! Então o cabeçalho inteiro, 'nome;turma;nota', virou o nome de uma coluna, com o valor 'Bia;A;8', e o 5 que sobrou depois da vírgula foi para uma chave None ("valores a mais, sem coluna"). Na linha 6, KeyError: 'nota': "chave não encontrada". Não existe nenhuma coluna chamada nota. Como consertar: csv.DictReader(arquivo, delimiter=";").

Vírgula decimal no float: ValueError
import csv

with open("notas_excel.csv", newline="", encoding="utf-8") as arquivo:
    for aluno in csv.DictReader(arquivo, delimiter=";"):
        print(float(aluno["nota"]))
$ python3 excel_float.py
Traceback (most recent call last):
  File "/home/ana/excel_float.py", line 5, in <module>
    print(float(aluno["nota"]))
          ~~~~~^^^^^^^^^^^^^^^
ValueError: could not convert string to float: '8,5'

"Não consegui converter o texto '8,5' em float." O separador já está certo; o problema agora é que o Python só entende o ponto decimal. Como consertar: float(aluno["nota"].replace(",", ".")).

O BOM grudado no cabeçalho: KeyError com a chave que "existe"
import csv

with open("notas_bom.csv", newline="", encoding="utf-8") as arquivo:
    for aluno in csv.DictReader(arquivo, delimiter=";"):
        print(aluno)
        print(aluno["nome"])
$ python3 bom.py
{'nome': 'Bia', 'turma': 'A', 'nota': '8,5'}
Traceback (most recent call last):
  File "/home/ana/bom.py", line 6, in <module>
    print(aluno["nome"])
          ~~~~~^^^^^^^^
KeyError: 'nome'

O mais confuso dos erros de CSV: o arquivo claramente tem a coluna nome, e mesmo assim KeyError: 'nome'. O print(aluno) revela o culpado: a chave é 'nome'. O  é o BOM, aquela marca invisível do começo do arquivo, que o "utf-8" leu como se fosse uma letra. Como consertar: encoding="utf-8-sig".

Chave que não está no fieldnames: ValueError
import csv

pedido = {"cliente": "Bia", "produto": "café", "qtd": 2}

with open("pedidos.csv", "w", newline="", encoding="utf-8") as arquivo:
    escritor = csv.DictWriter(arquivo, fieldnames=["cliente", "produto", "quantidade"])
    escritor.writeheader()
    escritor.writerow(pedido)
$ python3 dictw_erro.py
Traceback (most recent call last):
  File "/home/ana/dictw_erro.py", line 8, in <module>
    escritor.writerow(pedido)
    ~~~~~~~~~~~~~~~~~^^^^^^^^
  File "/usr/lib/python3.14/csv.py", line 225, in writerow
    return self.writer.writerow(self._dict_to_list(rowdict))
                                ~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/lib/python3.14/csv.py", line 220, in _dict_to_list
    raise ValueError("dict contains fields not in fieldnames: "
                     + ", ".join([repr(x) for x in wrong_fields]))
ValueError: dict contains fields not in fieldnames: 'qtd'

"O dicionário tem campos que não estão no fieldnames: 'qtd'." A sua linha é a 8; as de /usr/lib/python3.14/csv.py são de dentro do módulo. O dicionário usa qtd, e o escritor esperava quantidade. Como consertar: use o mesmo nome nos dois lugares. (Chave que falta no dicionário não dá erro: a coluna sai vazia.)

Usar o leitor depois do with: arquivo fechado
import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)

for linha in leitor:
    print(linha)
$ python3 fora_with.py
Traceback (most recent call last):
  File "/home/ana/fora_with.py", line 6, in <module>
    for linha in leitor:
                 ^^^^^^
ValueError: I/O operation on closed file.

"Operação de entrada/saída num arquivo fechado." O leitor não guarda os dados: ele vai lendo do arquivo aos poucos, e o with fechou o arquivo quando o bloco acabou. Como consertar: coloque o for dentro do with (com 4 espaços), ou leia tudo para uma lista lá dentro: linhas = list(leitor).

O leitor que "secou": a segunda volta vem vazia
import csv

with open("notas.csv", newline="", encoding="utf-8") as arquivo:
    leitor = csv.reader(arquivo)
    print("Primeira volta:", len(list(leitor)), "linhas")
    print("Segunda volta:", len(list(leitor)), "linhas")
$ python3 duas_vezes.py
Primeira volta: 5 linhas
Segunda volta: 0 linhas

Sem erro nenhum, a segunda volta não achou nada. O leitor é como ler um livro: depois que chegou à última página, continuar lendo não traz mais nada. Como consertar: leia uma vez para uma lista (linhas = list(leitor)) e percorra a lista quantas vezes quiser.


Referência rápida

EscritaO que faz
open(nome, newline="", encoding="utf-8")Abre para ler um CSV (para gravar, acrescente "w")
csv.reader(arquivo)Leitor: cada linha vira uma lista de textos
next(leitor)Tira a próxima linha (usado para pular o cabeçalho)
csv.DictReader(arquivo)Leitor: cada linha vira um dicionário com as chaves do cabeçalho
csv.writer(arquivo)Escritor de listas
escritor.writerow(lista) / writerows(listas)Grava uma linha / várias linhas
csv.DictWriter(arquivo, fieldnames=[…])Escritor de dicionários, com as colunas nessa ordem
escritor.writeheader()Grava a linha do cabeçalho
delimiter=";"Colunas separadas por ponto e vírgula (Excel brasileiro)
encoding="utf-8-sig"Lê pulando o BOM; grava com o BOM (bom para o Excel)
float(texto.replace(",", "."))Converte número com vírgula decimal
list(leitor)Todas as linhas numa lista (para usar mais de uma vez ou fora do with)
SintomaCausa provável
Uma coluna só, chamada 'nome;turma;nota', ou KeyError no DictReaderArquivo com ;: faltou delimiter=";"
ValueError: could not convert string to float: '8,5'Vírgula decimal: .replace(",", ".") antes do float
KeyError com uma chave que existe; a chave aparece como 'nome'BOM do Excel: use encoding="utf-8-sig"
TypeError: can only concatenate str (not "int") to strConta com um valor do CSV, que é texto: converta com int()/float()
ValueError: dict contains fields not in fieldnamesChave do dicionário diferente das do fieldnames
ValueError: I/O operation on closed file.Usou o leitor fora do with
Segunda leitura vazia, sem erroO leitor só anda para a frente: guarde numa lista
Linha em branco entre as linhas, no Excel do WindowsFaltou newline="" ao gravar

Exercícios

1. O que quer dizer

CSV são as iniciais de Comma-Separated Values: valores separados por… (uma palavra)

2. O arquivo do Excel

Complete para ler um CSV salvo pelo Excel em português:

leitor = csv.DictReader(arquivo, )

3. Pulando o cabeçalho

Complete para descartar a primeira linha antes do for:

leitor = csv.reader(arquivo)

for linha in leitor:

4. Com csv.DictReader, a linha Bia,A,8.5 vira {'nome': 'Bia', 'turma': 'A', 'nota': '8.5'}. Qual é o tipo de aluno["nota"]?

5. A Ana gravou ["Silva, Ana", "Teresina"] com csv.writer. Como a linha aparece no arquivo?

6. O DictReader deu KeyError: 'nome', e o print da linha mostra a chave 'nome'. O que resolve?

Missão final: a lista de compras em CSV

Missão: o programa grava compras.csv, mas só o cabeçalho. Faça ele gravar também os itens da lista compras (uma linha por item) e depois mostrar o arquivo. Dica: writerows.

import csv

compras = [
    ["arroz", 2],
    ["feijão", 1],
    ["café", 3],
]

with open("compras.csv", "w", newline="", encoding="utf-8") as arquivo:
    escritor = csv.writer(arquivo)
    escritor.writerow(["produto", "quantidade"])

with open("compras.csv", newline="", encoding="utf-8") as arquivo:
    print(arquivo.read())
import csv

compras = [
    ["arroz", 2],
    ["feijão", 1],
    ["café", 3],
]

with open("compras.csv", "w", newline="", encoding="utf-8") as arquivo:
    escritor = csv.writer(arquivo)
    escritor.writerow(["produto", "quantidade"])
    escritor.writerows(compras)

with open("compras.csv", newline="", encoding="utf-8") as arquivo:
    print(arquivo.read())

Quer ir além? Troque para delimiter=";" e encoding="utf-8-sig" e veja como o arquivo muda; é esse que abre direitinho no Excel em português. As notas da turma voltam no Projeto: Notas da Turma.


Resumo

  • CSV é uma tabela em texto: uma linha por registro, uma vírgula entre as colunas, e o cabeçalho na primeira linha.
  • Abra sempre com newline="" e encoding="utf-8": o módulo csv cuida das quebras de linha.
  • csv.reader dá listas; next(leitor) pula o cabeçalho. csv.DictReader dá dicionários com as chaves do cabeçalho.
  • Todo valor lido é texto: converta com int() ou float().
  • csv.writer + writerow/writerows gravam listas; csv.DictWriter(…, fieldnames=…) + writeheader() gravam dicionários. As aspas para valores com vírgula aparecem sozinhas.
  • Excel brasileiro: delimiter=";", vírgula decimal (.replace(",", ".")) e encoding="utf-8-sig" para o BOM.
  • O leitor só anda para a frente e só funciona com o arquivo aberto: para usar depois, list(leitor).