Unidade 5 · o caderno

O caderno

A fila na memória some ao encerrar. O caderno no disco continua: gravar, ler, CSV, with.

Nesta unidade Lista de nomes morre no Encerrar. "w" recria e deixa só o último. "a" acrescenta. write não põe \n. with fecha. CSV: vírgula no endereço quebra o split — use o módulo csv.

O que some quando o programa acaba

Variável, lista, dicionário: memória. Fecha o terminal, acabou. No computador você já sabe o contrário: um arquivo continua. Ler e gravar no disco é o caderno desta unidade.

fila.py: três nomes, como na unidade 3. for _ in range(3), input, append, sorted, print. Ana, Bia, Leo. Rode de novo: o interpretador não lembra. A lista nasceu e morreu neste processo.

nomes = []
for _ in range(3):
    nomes.append(input("nome? "))
for nome in sorted(nomes):
    print(nome)

Gravar: o modo que apaga

open("fila.txt", "w") devolve um objeto arquivo. .write(nome), depois .close(). Sem fechar, o sistema pode não despejar o buffer no disco.

"w" de write: se o arquivo não existe, cria; se existe, zera e começa do zero. No loop, cada volta abre de novo com w: Ana entra, some; Bia entra, some; fica só Leo. O write não é o vilão — o modo recria o arquivo a cada open.

5.A · w no loop

Três vezes: open(..., "w"), write de um nome, close. O que resta em fila.txt?

w de write, mas também de “wipe” informal.
Abrir de novo com w não continua de onde parou.
Solução: só o último. Use a, ou um único open fora do loop.

Acrescentar

"a" de append: cola no fim, não apaga o começo. Três opens com a guardam Ana, Bia e Leo. Ainda assim, sem quebra de linha, vira AnaBiaLeo.

5.B · modo

Qual modo apaga o conteúdo anterior do arquivo?

Um dos dois modos de escrita destrói; o outro cola no fim.
w de write, a de append.
Solução: "w".

write não é print

print já entrega \n no fim (unidade 1, end). write grava só o que você passou. Sem \n, os nomes colam. Com f"{nome}\n", cada um numa linha.

5.C · sem quebra

arquivo.write(nome) três vezes no modo a, sem \n. O que o arquivo contém?

print e write não são a mesma função.
a acrescenta bytes; não formata linha.
Solução: colados. Passe a quebra no write.
5.D · write

Um trecho que grave texto com .write(...).

f.write("uma linha\n")
Pode ir dentro de um with open.
Exemplo: f.write("Café na máquina.\n")

O close de graça

Esquecer close é fácil. Crash no meio deixa o arquivo aberto. with open(...) as arquivo: fecha ao sair do bloco — erro ou não. É o try/finally da unidade 6, embutido — aqui você já usa o atalho. Daqui para frente, with.

with open("fila.txt", "a", encoding="utf-8") as arquivo:
    arquivo.write(f"{nome}\n")

No Windows brasileiro, sem encoding="utf-8", acento vira surpresa. Sempre passe.

5.E · open

Uma linha (ou bloco) que abra um arquivo com open ou with open.

with open("fila.txt", encoding="utf-8") as arquivo:
O bloco indentado usa o arquivo.
Exemplo: with open("nota.txt", "w", encoding="utf-8") as f:

Ler de volta

Sem letra, o padrão é "r": só leitura. Arquivo inexistente: FileNotFoundError. readlines() devolve lista de strings — cada uma ainda traz o \n do arquivo. print(linha) põe outro \n: linha em branco extra. linha.rstrip() tira o da direita; o print cuida do resto. Ou print(linha, end="").

Melhor: for linha in arquivo: — o objeto arquivo já é iterável, uma linha por vez, sem carregar o arquivo inteiro na lista.

5.F · linha em branco

O arquivo tem Ana\n. Você faz print(linha) sem rstrip. Por que aparece uma linha vazia extra?

Duas quebras, duas origens.
rstrip no fim da linha; print no fim da chamada.
Solução: arquivo + print. Tire uma das duas.

Não dá para ordenar enquanto imprime

Imprimir linha a linha não ordena o conjunto. O arquivo pode ter Leo, Ana, Bia. Você quer Ana, Bia, Leo. Acumule numa lista (já rstrip), depois sorted(nomes) ou sorted(..., reverse=True). O disco não vem sortido só porque você quer.

nomes = []
with open("fila.txt", encoding="utf-8") as arquivo:
    for linha in arquivo:
        nomes.append(linha.rstrip())
for nome in sorted(nomes):
    print(nome)

nome, via

Um campo só não chega. Ficha: nome e via (mesa ou balcão). Arquivo fichas.csv, duas colunas:

Ana,mesa
Bia,balcão
Leo,mesa

Na mão: linha.split(","), row[0] e row[1], ou unpack nome, via = linha.strip().split(",").

Imprimir e depois querer ordem alfabética por nome: lista de frases f"{nome} · {via}" e sorted — frágil (via no meio da string). Lista de dicts: {"nome": nome, "via": via}, depois sorted(fichas, key=get_nome) ou key=lambda f: f["nome"] (unidade 10 aprofunda lambda; aqui já serve).

Rua do Forno, 12

Endereço com vírgula: Ana,Rua do Forno, 12. split(",") acha três pedaços. nome, via = ... espera dois: ValueError: too many values to unpack. O dado quebrou o contrato, não o Python.

5.G · vírgula extra

nome, via = linha.split(",") e a linha é Ana,Rua do Forno, 12. O que acontece?

split não sabe o que é endereço.
O módulo csv trata campo entre aspas.
Solução: ValueError. csv.reader (ou aspas no arquivo).

Deixe a biblioteca fatiar

import csv. csv.reader(arquivo) entrega lista por linha e respeita aspas: "Rua do Forno, 12" é um campo. Ainda é índice 0 e 1.

csv.DictReader: a primeira linha é cabeçalho. Cada linha vira dict. linha["nome"], linha["via"]. Inverta as colunas no arquivo — o print pelas chaves continua. Coluna a mais no CSV, o código antigo ignora. Unidade 3: a mesma ficha, agora persistente.

import csv

with open("fichas.csv", encoding="utf-8") as f:
    for linha in csv.DictReader(f):
        print(linha["nome"], "·", linha["via"])
5.H · DictReader

Por que csv.DictReader combina com dicionários?

Cabeçalho nome,via → chave "nome".
É o mesmo tipo da lista de fichas.
Solução: cada linha é um dicionário.
5.I · colunas trocadas

O CSV tem cabeçalho via,nome (invertido). O código faz print(linha["nome"]) com DictReader. O que acontece?

row[0] assume ordem. Dict não.
A primeira linha nomeia as colunas.
Solução: a chave "nome" acha a coluna certa.

Gravar a tabela

Ler é metade. O caixa acrescenta ficha. csv.writer e csv.DictWriter gravam a tabela: a biblioteca põe aspas no campo que tem vírgula — Rua do Forno, 12 volta a ser um campo, não três. writeheader() na primeira vez. writerow({...}) nas seguintes. Append: modo "a", sem repetir o cabeçalho se o arquivo já existe. newline="" no open evita linha em branco extra no Windows.

import csv

with open("fichas.csv", "a", encoding="utf-8", newline="") as f:
    w = csv.DictWriter(f, fieldnames=["nome", "via"])
    w.writerow({"nome": nome, "via": via})

Não é só texto

Imagem, áudio, PDF: bytes, não linhas de str. open(..., "rb") / "wb". Bibliotecas de imagem existem; nesta trilha o recado é saber que o modo binário existe. Texto e CSV já resolvem a fila da padaria.

Oficina · fichas.csv

Problema da unidade Escreva ou leia um arquivo (texto da fila ou CSV nome/via) e mostre algo no terminal. Arquivo: fila.py ou agenda.py.
Oficina 5

Cole um programa que abra arquivo (open/csv) e leia ou grave.

with open("fila.txt", "a", encoding="utf-8") as f: f.write("Ana\n")
Ou DictReader num csv.
Modelo:
with open("fila.txt", "w", encoding="utf-8") as f:
    f.write("Ana\n")
print("gravado")