Skip to content

    Chapter 24, Basic

    Files and pathlib

    Reading and writing files is the first time your program touches the outside world. I show the safe way: `with`, explicit encoding, and `pathlib`.

    Code for this chapter: basico/cap24_arquivos.py

    Open with with

    The with ensures that the file is closed, even if an error occurs in the middle. I always pass encoding="utf-8" explicitly:

    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")
    
    Output
    primeira linha
    segunda linha com acentuação
    

    Why specify the encoding

    If you do not specify the encoding, Python uses the system default. On Windows, this historically was not UTF-8, and the code that worked on your Mac broke with accents on a colleague's machine. Python 3.15 now uses UTF-8 as the default (PEP 686), but earlier versions still depend on the system, so the rule still applies: always explicit.

    Opening modes

    ModeEffectDoes it create the file?
    "r"Reading (default). Fails if it does not existNo
    "w"Writing. Deletes the existing contentYes
    "a"Appends to the endYes
    "x"Exclusive creation. Fails if it already existsYes
    "b"Appended to others for binary mode ("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")
    
    Output
    notas.txt já existe, o modo x recusou
    

    Read line by line

    read() ) loads the entire file into memory. For large files, iterate through the file with for: Python reads one line at a time:

    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"))
    
    Output
    1 primeira linha
    2 segunda linha com acentuação
    3 terceira linha
    

    pathlib

    Building paths with text ("pasta/" + nome) breaks between operating systems. The pathlib treats paths as objects, with the operator / and ready methods:

    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)
    
    Output
    total: 42
    relatorio.txt relatorio .txt saida
    True False
    saida/relatorio.txt
    

    Common errors

    The most common error is FileNotFoundError. And almost always the reason is the current directory: a relative path like "dados/entrada.txt" is resolved from the folder where you executed the command, not from the script's folder. To locate files next to the script, start from __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)
    
    Output
    [Errno 2] No such file or directory: 'nao_existe.txt'
    dados
    

    Exercise 1

    Count lines and words

    Write estatisticas(caminho) that returns (linhas, palavras) in a file, reading one line at a time.