Pular para o conteúdo

    Capítulo 24, Básico

    Arquivos e pathlib

    Ler e gravar arquivos é a primeira vez que o seu programa toca o mundo de fora. Eu mostro o jeito seguro: `with`, codificação explícita e `pathlib`.

    Código deste capítulo: basico/cap24_arquivos.py

    Abrir com with

    O with garante que o arquivo seja fechado, mesmo que ocorra um erro no meio. Eu sempre passo encoding="utf-8" de forma explícita:

    basico/cap24_arquivos.pylinhas 10 a 19
    with open("notas.txt", "w", encoding="utf-8") as arquivo:
        arquivo.write("primeira linha\n")
        arquivo.write("segunda linha com acentuação\n")
    
    with open("notas.txt", "r", encoding="utf-8") as arquivo:
        conteudo = arquivo.read()
    print(conteudo)
    
    with open("notas.txt", "a", encoding="utf-8") as arquivo:
        arquivo.write("terceira linha\n")
    
    Saída
    primeira linha
    segunda linha com acentuação
    

    Por que dizer o encoding

    Se você não informa a codificação, o Python usa a padrão do sistema. No Windows, isso historicamente não era UTF-8, e o código que funcionava no seu Mac quebrava com acentos na máquina de um colega. O Python 3.15 passa a usar UTF-8 como padrão (PEP 686), mas versões anteriores continuam dependendo do sistema, então a regra continua valendo: sempre explícito.

    Modos de abertura

    ModoEfeitoCria o arquivo?
    "r"Leitura (padrão). Falha se não existirNão
    "w"Escrita. Apaga o conteúdo existenteSim
    "a"Acrescenta ao finalSim
    "x"Criação exclusiva. Falha se já existirSim
    "b"Acrescentado aos demais para modo binário ("rb", "wb")
    basico/cap24_arquivos.pylinhas 24 a 28
    try:
        with open("notas.txt", "x", encoding="utf-8") as arquivo:
            arquivo.write("não vai acontecer")
    except FileExistsError:
        print("notas.txt já existe, o modo x recusou")
    
    Saída
    notas.txt já existe, o modo x recusou
    

    Ler linha por linha

    read() carrega o arquivo inteiro na memória. Para arquivos grandes, percorra o arquivo com for: o Python lê uma linha por vez:

    basico/cap24_arquivos.pylinhas 33 a 35
    with open("notas.txt", encoding="utf-8") as arquivo:
        for numero, linha in enumerate(arquivo, start=1):
            print(numero, linha.rstrip("\n"))
    
    Saída
    1 primeira linha
    2 segunda linha com acentuação
    3 terceira linha
    

    pathlib

    Montar caminhos com texto ("pasta/" + nome) quebra entre sistemas operacionais. O pathlib trata caminhos como objetos, com o operador / e métodos prontos:

    basico/cap24_arquivos.pylinhas 40 a 50
    from pathlib import Path
    
    pasta = Path("saida")
    pasta.mkdir(exist_ok=True)
    arquivo = pasta / "relatorio.txt"
    arquivo.write_text("total: 42\n", encoding="utf-8")
    print(arquivo.read_text(encoding="utf-8").strip())
    print(arquivo.name, arquivo.stem, arquivo.suffix, arquivo.parent)
    print(arquivo.exists(), (pasta / "nao_existe.txt").exists())
    for item in sorted(pasta.glob("*.txt")):
        print(item)
    
    Saída
    total: 42
    relatorio.txt relatorio .txt saida
    True False
    saida/relatorio.txt
    

    Erros comuns

    O erro mais comum é FileNotFoundError. E quase sempre o motivo é o diretório atual: um caminho relativo como "dados/entrada.txt" é resolvido a partir da pasta onde você executou o comando, não da pasta do script. Para localizar arquivos ao lado do script, parta de __file__:

    basico/cap24_arquivos.pylinhas 55 a 61
    try:
        open("nao_existe.txt", encoding="utf-8")
    except FileNotFoundError as erro:
        print(erro)
    
    base = Path(__file__).parent
    print((base / "dados").name)
    
    Saída
    [Errno 2] No such file or directory: 'nao_existe.txt'
    dados
    

    Exercício 1

    Contar linhas e palavras

    Escreva estatisticas(caminho) que devolva (linhas, palavras) de um arquivo, lendo uma linha por vez.