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.
- O que tem dentro de um arquivo CSV.
- A ler as linhas como listas com
csv.readere pular o cabeçalho comnext(). - Que tudo o que vem do CSV é texto, e como converter para número.
- A gravar com
csv.writer,writerowewriterows. - Por que sempre abrir com
newline="". - A ler cada linha como um dicionário com
DictReadere gravar comDictWriter. - O CSV do Excel brasileiro: ponto e vírgula (
delimiter=";"), vírgula decimal e outf-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".
| nome | turma | nota |
|---|---|---|
| Bia | A | 8.5 |
| Caio | B | 6.0 |
| Duda | A | 9.5 |
| Enzo | B | 7.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ódulocsvcuidar 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
forque vem depois continua de onde onextparou: 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
opentroca cada\npor\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 oopennã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="", oopenaltera essa quebra antes de o leitor ver.
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.writerecsv.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 ofloatentende. - .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.
| Forma | Cada linha vira | Quando usar |
|---|---|---|
csv.reader | Lista: ['Bia', 'A', '8.5'] | Arquivos sem cabeçalho, ou quando você quer as colunas pela posição |
csv.DictReader | Dicioná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(",") | Lista | Só para arquivos que você controla e que nunca têm vírgula nem aspas nos valores. Na dúvida, use o csv |
| Para gravar | Você entrega | Quando usar |
|---|---|---|
csv.writer + writerow | Listas | Os dados já estão em listas |
csv.DictWriter + writeheader + writerow | Dicionários | Os dados estão em dicionários (o caso do JSON, por exemplo) |
Quando dá errado
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=";").
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(",", ".")).
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".
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.)
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).
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
| Escrita | O 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) |
| Sintoma | Causa provável |
|---|---|
Uma coluna só, chamada 'nome;turma;nota', ou KeyError no DictReader | Arquivo 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 str | Conta com um valor do CSV, que é texto: converta com int()/float() |
ValueError: dict contains fields not in fieldnames | Chave do dicionário diferente das do fieldnames |
ValueError: I/O operation on closed file. | Usou o leitor fora do with |
| Segunda leitura vazia, sem erro | O leitor só anda para a frente: guarde numa lista |
| Linha em branco entre as linhas, no Excel do Windows | Faltou 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:
3. Pulando o cabeçalho
Complete para descartar a primeira linha antes do for:
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=""eencoding="utf-8": o módulocsvcuida das quebras de linha. csv.readerdá listas;next(leitor)pula o cabeçalho.csv.DictReaderdá dicionários com as chaves do cabeçalho.- Todo valor lido é texto: converta com
int()oufloat(). csv.writer+writerow/writerowsgravam listas;csv.DictWriter(…, fieldnames=…)+writeheader()gravam dicionários. As aspas para valores com vírgula aparecem sozinhas.- Excel brasileiro:
delimiter=";", vírgula decimal (.replace(",", ".")) eencoding="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).