Python pathlib

Nas aulas anteriores, a Ana abriu, leu e gravou arquivos com open(). Mas os arquivos de verdade não ficam soltos: ficam dentro de pastas, que ficam dentro de outras pastas. A lojinha da Ana já tem uma pasta loja, com a lista de produtos, a lista de clientes e uma pasta só para as vendas de cada mês. Para o programa saber onde cada arquivo está, criar pastas novas, conferir se um arquivo existe antes de abrir e listar o que há dentro de uma pasta, o Python tem o módulo pathlib (de path, "caminho", e lib, de library, "biblioteca").

Você vai aprender
  • O que é um caminho e como criar um com Path.
  • A juntar pedaços de caminho com a barra /, sem se preocupar com o sistema.
  • A pegar as partes de um caminho: name, stem, suffix, parent.
  • A perguntar se um arquivo ou pasta existe: exists(), is_file(), is_dir().
  • A criar pastas com mkdir(), e as opções parents e exist_ok.
  • A ler e gravar um arquivo inteiro numa linha: read_text() e write_text().
  • A listar uma pasta com iterdir() e procurar arquivos com glob() e rglob().
  • Os erros reais: FileNotFoundError, FileExistsError, IsADirectoryError, a barra entre dois textos e a pasta que não está vazia.

A ideia: o endereço de um arquivo

Para mandar uma carta para a Ana, você escreve o endereço do mais geral para o mais específico: cidade, bairro, rua, número. O computador faz igual com os arquivos. O arquivo janeiro.txt da lojinha mora assim:

/home/ana/loja/vendas/janeiro.txt

Lendo da esquerda para a direita: começando da raiz do disco (a primeira /), entre na pasta home, depois na pasta ana, depois em loja, depois em vendas, e lá dentro está o arquivo janeiro.txt. Esse "endereço" se chama caminho (em inglês, path). Cada / separa uma pasta da próxima.

Tipo de caminhoExemploQuer dizer
Absoluto (completo)/home/ana/loja/produtos.txtO endereço inteiro, a partir da raiz do disco. Começa com /
Relativoloja/produtos.txt"A partir de onde eu estou agora": a pasta loja que está na pasta atual

Quando você roda python3 programa.py no terminal da Ana, a "pasta atual" é a pasta em que o terminal está (no começo, /home/ana). No editor do guia, é a pasta do programa. Nos exemplos desta aula, quase todos os caminhos são relativos: funcionam igual nos dois lugares.


1. O primeiro Path

Dentro do módulo pathlib mora o Path ("caminho"). Você o traz para o seu programa com from pathlib import Path (a aula Módulos e import explica essa linha em detalhe) e cria um caminho passando o texto dele:

from pathlib import Path

arquivo = Path("compras.txt")
print(arquivo)
print(type(arquivo))
from pathlib import Path
"Do módulo pathlib, traga o Path." Sem essa linha, o Python não conhece o nome Path.
Path("compras.txt")
Cria um objeto caminho a partir do texto "compras.txt". Ele ainda não abre nem cria nada: é só o endereço, anotado num papel.
arquivo = …
Guarda o caminho na variável arquivo, como qualquer outro valor.
print(arquivo)
Mostra o caminho como texto.
$ python3 caminho.py
compras.txt
<class 'pathlib.PosixPath'>

O print mostrou o caminho sem aspas, e o type revelou que ele não é um texto (str), e sim um PosixPath: um caminho no estilo do Linux e do macOS (POSIX é o nome do padrão que esses sistemas seguem). No Windows, o mesmo programa mostraria WindowsPath. Você não precisa escolher: escreva sempre Path, e o Python usa o tipo certo para o sistema.

O caminho não precisa existir

Repare que não existe nenhum compras.txt na pasta da Ana, e mesmo assim o programa funcionou. Criar um Path é como anotar um endereço: anotar não constrói a casa. O erro só aparece quando você tenta usar o arquivo (ler, por exemplo), como você vai ver em Quando dá errado.


2. Juntando pedaços com a barra /

O jeito mais bonito do pathlib é a barra. Entre um Path e um texto, o / não é divisão: é "entre nesta pasta". Assim você monta um caminho pedaço por pedaço:

from pathlib import Path

pasta = Path("loja")
arquivo = pasta / "vendas" / "janeiro.txt"

print(arquivo)
print("Nome:", arquivo.name)
print("Sem a extensão:", arquivo.stem)
print("Extensão:", arquivo.suffix)
print("Pasta onde está:", arquivo.parent)
print("Partes:", arquivo.parts)
$ python3 partes.py
loja/vendas/janeiro.txt
Nome: janeiro.txt
Sem a extensão: janeiro
Extensão: .txt
Pasta onde está: loja/vendas
Partes: ('loja', 'vendas', 'janeiro.txt')
pasta / "vendas"
Um Path barra um texto dá um Path novo: loja/vendas. Dá para encadear quantas barras quiser.
.name
O nome do último pedaço, com a extensão: janeiro.txt.
.stem
O nome sem a extensão (stem = "talo", a parte principal): janeiro.
.suffix
A extensão, com o ponto (suffix = "sufixo"): .txt.
.parent
A pasta "mãe", onde o arquivo está (parent = "pai/mãe"): loja/vendas. Também é um Path.
.parts
Todos os pedaços, numa tupla.

Repare: name, stem, suffix e parent não levam parênteses. Eles não fazem nada no disco; só leem pedaços do próprio endereço. São atributos, informações que o objeto já tem.

Por que não escrever "loja/vendas/janeiro.txt" de uma vez?

Funciona no Linux, mas o Windows separa as pastas com a barra invertida (loja\vendas\janeiro.txt). Com Path("loja") / "vendas" / "janeiro.txt", o Python escreve o separador certo para cada sistema, e o seu programa roda nos dois sem mudar uma letra.

Missão: a Ana guardou as vendas de março no arquivo marco.txt, dentro da pasta 2026, que fica dentro de vendas, que fica dentro de loja. Monte esse caminho com barras / a partir de Path("loja") e rode: o programa deve mostrar o caminho e a extensão.

from pathlib import Path

arquivo = Path("loja")

print(arquivo)
print("Extensão:", arquivo.suffix)
from pathlib import Path

arquivo = Path("loja") / "vendas" / "2026" / "marco.txt"

print(arquivo)
print("Extensão:", arquivo.suffix)

3. Onde eu estou? cwd(), home() e absolute()

Três perguntas que o Path responde sobre o computador:

from pathlib import Path

print("Pasta atual:", Path.cwd())
print("Pasta pessoal:", Path.home())

arquivo = Path("compras.txt")
print("Caminho completo:", arquivo.absolute())
$ python3 onde.py
Pasta atual: /home/ana
Pasta pessoal: /home/ana
Caminho completo: /home/ana/compras.txt
EscritaO que responde
Path.cwd()A pasta atual (current working directory, "pasta de trabalho atual"): de onde partem os caminhos relativos
Path.home()A pasta pessoal do usuário: /home/ana para a Ana
caminho.absolute()O caminho relativo transformado em absoluto, grudando a pasta atual na frente

Esses três dependem do computador: num outro usuário, ou no editor do guia, as respostas são outras. Por isso eles servem para mostrar onde as coisas estão, mas um programa que você vai mandar para outras pessoas não deve ter /home/ana escrito dentro dele.


4. Existe? É arquivo? É pasta?

Antes de abrir um arquivo, dá para perguntar se ele está lá. As respostas são booleanos (True ou False):

from pathlib import Path

for nome in ["Documentos", "compras.txt", "existe.py"]:
    caminho = Path(nome)
    print(nome)
    print("  existe?", caminho.exists())
    print("  é arquivo?", caminho.is_file())
    print("  é pasta?", caminho.is_dir())
$ python3 existe.py
Documentos
  existe? True
  é arquivo? False
  é pasta? True
compras.txt
  existe? False
  é arquivo? False
  é pasta? False
existe.py
  existe? True
  é arquivo? True
  é pasta? False
.exists()
"Existe?" Verdadeiro se houver qualquer coisa com esse nome: arquivo ou pasta.
.is_file()
"É um arquivo?" Falso para pastas e para o que não existe.
.is_dir()
"É uma pasta?" (dir vem de directory, "diretório", outro nome para pasta.)

Esses levam parênteses: são métodos, ações que vão até o disco olhar. A pasta Documentos existe e é pasta; compras.txt não existe, então as três respostas são False; e o próprio programa existe.py é um arquivo.

O uso mais comum é num if, para não tentar ler o que não está lá:

from pathlib import Path

arquivo = Path("loja") / "produtos.txt"
if arquivo.exists():
    print(arquivo.read_text(encoding="utf-8"))
else:
    print("Ainda não existe a lista de produtos.")

Rodando agora, que a lista ainda não foi criada, e depois da seção 6, quando ela já existir:

$ python3 conferir.py                   « antes de existir o loja/produtos.txt
Ainda não existe a lista de produtos.
$ python3 conferir.py                   « depois
café
açúcar
pão de queijo


5. Criando pastas: mkdir()

mkdir vem de make directory, "criar pasta" (o mesmo nome do comando do terminal). A Ana vai criar a pasta da loja e, dentro dela, vendas/2026:

from pathlib import Path

loja = Path("loja")
loja.mkdir()
print("Criei a pasta", loja)

vendas = loja / "vendas" / "2026"
vendas.mkdir(parents=True)
print("Criei a pasta", vendas)

loja.mkdir(exist_ok=True)
print("A pasta loja já existia, e tudo bem")
$ python3 pastas.py
Criei a pasta loja
Criei a pasta loja/vendas/2026
A pasta loja já existia, e tudo bem
$ tree loja                             « o comando tree desenha as pastas
loja
└── vendas
    └── 2026

3 directories, 0 files
loja.mkdir()
Cria uma pasta. A pasta de cima tem de existir (aqui é a pasta atual, que existe).
mkdir(parents=True)
Cria também as pastas do meio que faltarem (parents = "os pais"). Sem isso, criar loja/vendas/2026 daria erro, porque vendas ainda não existia.
mkdir(exist_ok=True)
"Tudo bem se já existir" (exist ok). Sem isso, criar uma pasta que já existe dá erro.

O tree ("árvore") é um programa do terminal que desenha as pastas uma dentro da outra; a última linha (em inglês) conta 3 pastas e nenhum arquivo. E se a Ana rodar o programa de novo? A primeira linha, loja.mkdir(), sem exist_ok, tenta criar uma pasta que agora existe:

$ python3 pastas.py
Traceback (most recent call last):
  File "/home/ana/pastas.py", line 4, in <module>
    loja.mkdir()
    ~~~~~~~~~~^^
  File "/usr/lib/python3.14/pathlib/__init__.py", line 1012, in mkdir
    os.mkdir(self, mode)
    ~~~~~~~~^^^^^^^^^^^^
FileExistsError: [Errno 17] File exists: 'loja'

Leia o traceback de baixo para cima. A última linha é o que aconteceu: FileExistsError, "erro: o arquivo existe", File exists: 'loja'. Para o sistema, uma pasta também é um tipo de "arquivo", por isso a mensagem fala em file. Acima dela há dois trechos de código: o primeiro é a linha 4 do programa da Ana (loja.mkdir()); o segundo é de dentro do próprio pathlib, onde o erro de fato estourou. Quando o traceback passa por arquivos do Python (os que começam com /usr/lib/python3.14/), procure a última linha que é sua: é ela que você conserta.

A receita que não falha, e que você vai ver em muitos programas, é juntar as duas opções:

from pathlib import Path

Path("loja", "vendas", "2026").mkdir(parents=True, exist_ok=True)
print("Pronto, e sem erro")
$ python3 receita.py
Pronto, e sem erro
$ python3 receita.py                    « de novo: nada de FileExistsError
Pronto, e sem erro

Cria o que faltar e não reclama do que já existe. (Repare em mais um jeito de montar o caminho: Path("loja", "vendas", "2026"), com os pedaços separados por vírgula, é o mesmo que Path("loja") / "vendas" / "2026".)


6. Ler e gravar sem open(): read_text() e write_text()

Para arquivos de texto pequenos, o Path tem dois atalhos que fazem o open, o with, o read/write e o fechamento numa linha só:

from pathlib import Path

arquivo = Path("loja") / "produtos.txt"
arquivo.write_text("café\naçúcar\npão de queijo\n", encoding="utf-8")
print("Gravei", arquivo)

texto = arquivo.read_text(encoding="utf-8")
print(texto)
print("O arquivo tem", len(texto.splitlines()), "linhas")
$ python3 escrever.py
Gravei loja/produtos.txt
café
açúcar
pão de queijo

O arquivo tem 3 linhas
$ cat loja/produtos.txt                 « o cat do terminal mostra o arquivo gravado
café
açúcar
pão de queijo
arquivo.write_text(texto, encoding="utf-8")
"Escreva este texto": cria o arquivo (ou apaga o conteúdo antigo e escreve por cima, como o modo "w" do open), grava e fecha.
arquivo.read_text(encoding="utf-8")
"Leia o texto": abre, lê tudo num str só e fecha.
encoding="utf-8"
A codificação, que diz como os acentos viram bytes. Sempre escreva, como você aprendeu em Abrindo Arquivos: assim o "café" chega inteiro em qualquer computador.

A linha em branco depois de "pão de queijo" é o \n do fim do arquivo somado ao \n do próprio print. O splitlines() quebra o texto nas linhas e o len conta: 3.

Quero…Com openCom Path
Ler tudo de uma vezwith open(p, encoding="utf-8") as f:
    texto = f.read()
texto = p.read_text(encoding="utf-8")
Gravar tudo de uma vezwith open(p, "w", encoding="utf-8") as f:
    f.write(texto)
p.write_text(texto, encoding="utf-8")
Ler linha por linha, acrescentar no fim ("a"), arquivos grandeswith open(p, …) as f:with p.open(…) as f: (o mesmo open, chamado pelo caminho)

O open() aceita um Path no lugar do texto do nome: open(arquivo, encoding="utf-8") funciona. Tudo o que você aprendeu em Lendo Arquivos e Escrevendo Arquivos continua valendo.

Missão: o programa quer gravar a lista de compras em mercado/lista.txt, mas a pasta mercado não existe e ele dá FileNotFoundError. Rode para ver o erro e conserte: crie a pasta antes de gravar.

from pathlib import Path

pasta = Path("mercado")
lista = pasta / "lista.txt"

lista.write_text("arroz\nfeijão\n", encoding="utf-8")
print(lista.read_text(encoding="utf-8"))
from pathlib import Path

pasta = Path("mercado")
lista = pasta / "lista.txt"

pasta.mkdir(exist_ok=True)
lista.write_text("arroz\nfeijão\n", encoding="utf-8")
print(lista.read_text(encoding="utf-8"))

7. O que tem dentro da pasta? iterdir()

A loja da Ana foi crescendo. Ela criou mais alguns arquivos (aqui com o touch do terminal, que cria arquivos vazios) e o tree mostra como ficou:

$ touch loja/clientes.txt loja/vendas/janeiro.txt loja/vendas/fevereiro.txt loja/vendas/notas.csv loja/vendas/2026/marco.txt
$ tree loja
loja
├── clientes.txt
├── produtos.txt
└── vendas
    ├── 2026
    │   └── marco.txt
    ├── fevereiro.txt
    ├── janeiro.txt
    └── notas.csv

3 directories, 6 files

Para o programa descobrir o que tem dentro de uma pasta, use iterdir() (de iterate directory, "percorrer a pasta"). Ele entrega um Path para cada coisa que está diretamente dentro da pasta:

from pathlib import Path

loja = Path("loja")
for item in sorted(loja.iterdir()):
    if item.is_dir():
        print("[pasta]  ", item.name)
    else:
        print("[arquivo]", item.name)
$ python3 listar.py
[arquivo] clientes.txt
[arquivo] produtos.txt
[pasta]   vendas
loja.iterdir()
Os itens que estão dentro de loja, um por vez, cada um como um Path (loja/clientes.txt, loja/vendas…). Não entra nas subpastas: o que está dentro de vendas não aparece.
sorted(…)
Coloca em ordem alfabética (aula Ordenando Listas).
item.is_dir()
Separa as pastas dos arquivos.
item.name
Só o nome, sem o loja/ na frente.
Sem sorted, a ordem é a do disco

O iterdir() entrega os itens na ordem em que o sistema guardou, que não é alfabética e pode mudar de um computador para outro. Se a ordem importa (quase sempre importa, para quem lê), passe por sorted().


8. Procurando arquivos: glob() e rglob()

E se a Ana quiser só os arquivos .txt? O glob procura pelos nomes que combinam com um molde, onde o * quer dizer "qualquer coisa" (é o mesmo curinga do terminal: ls *.txt).

from pathlib import Path

loja = Path("loja")

print("Os .txt da pasta loja:")
for arquivo in sorted(loja.glob("*.txt")):
    print(" ", arquivo)

print("Os .txt em qualquer lugar dentro de loja:")
for arquivo in sorted(loja.rglob("*.txt")):
    print(" ", arquivo)
$ python3 procurar.py
Os .txt da pasta loja:
  loja/clientes.txt
  loja/produtos.txt
Os .txt em qualquer lugar dentro de loja:
  loja/clientes.txt
  loja/produtos.txt
  loja/vendas/2026/marco.txt
  loja/vendas/fevereiro.txt
  loja/vendas/janeiro.txt
MoldeEncontra
loja.glob("*.txt")Os nomes terminados em .txt direto em loja
loja.glob("*")Tudo o que está direto em loja (parecido com iterdir())
loja.glob("vendas/*.csv")Os .csv dentro de loja/vendas
loja.glob("*a*")Os nomes que têm a letra a em qualquer lugar
loja.glob("vendas/janeiro.???")? é exatamente um caractere qualquer: janeiro.txt, janeiro.csv…
loja.rglob("*.txt")Os .txt em loja e em todas as subpastas, até o fundo (r de recursive, "recursivo")

O notas.csv não apareceu em nenhuma das duas buscas: o molde pedia .txt. E o rglob desceu até vendas/2026/marco.txt, que o glob não enxerga. Como no iterdir, use sorted() para ter uma ordem garantida.


9. Apagando: unlink() e rmdir()

from pathlib import Path

rascunho = Path("loja") / "rascunho.txt"
rascunho.write_text("teste\n", encoding="utf-8")
print("Existe?", rascunho.exists())

rascunho.unlink()
print("Depois do unlink, existe?", rascunho.exists())

rascunho.unlink(missing_ok=True)
print("Apagar de novo, com missing_ok=True, não deu erro")

vazia = Path("loja") / "vazia"
vazia.mkdir()
vazia.rmdir()
print("A pasta vazia foi apagada:", not vazia.exists())
$ python3 apagar.py
Existe? True
Depois do unlink, existe? False
Apagar de novo, com missing_ok=True, não deu erro
A pasta vazia foi apagada: True
.unlink()
Apaga um arquivo (unlink = "desligar", o nome técnico de apagar no Linux). Se o arquivo não existir, dá FileNotFoundError.
.unlink(missing_ok=True)
"Tudo bem se estiver faltando": não reclama se o arquivo já não existe.
.rmdir()
Apaga uma pasta vazia (remove directory). Com qualquer coisa dentro, ela se recusa.
Apagar é para sempre

O unlink() não manda o arquivo para a lixeira: ele some de vez, sem pergunta. Antes de rodar um programa que apaga arquivos, confira o caminho com um print. Que o rmdir() só apague pastas vazias é uma proteção a seu favor.


Formas diferentes de montar um caminho

Antes do pathlib (que existe desde o Python 3.4), os caminhos eram textos comuns, montados com a função os.path.join. Você ainda vai encontrar muito código assim:

import os.path
from pathlib import Path

jeito_antigo = os.path.join("loja", "vendas", "janeiro.txt")
jeito_novo = Path("loja") / "vendas" / "janeiro.txt"

print(jeito_antigo, type(jeito_antigo))
print(jeito_novo, type(jeito_novo))
print(str(jeito_novo) == jeito_antigo)
$ python3 ospath.py
loja/vendas/janeiro.txt <class 'str'>
loja/vendas/janeiro.txt <class 'pathlib.PosixPath'>
True

O mesmo endereço, só que um é texto e o outro é um Path. O str(caminho) transforma o Path em texto quando alguma função antiga exigir.

FormaQuando usar
Path("loja") / "vendas" / "janeiro.txt"O jeito moderno e o do guia. Fácil de ler, funciona em qualquer sistema e já dá acesso a name, exists(), read_text()…
Path("loja", "vendas", "janeiro.txt")O mesmo caminho; prático quando os pedaços já estão separados
Path("loja/vendas/janeiro.txt")Funciona; o Path entende a / no texto, até no Windows. Bom para caminhos fixos e curtos
os.path.join("loja", "vendas", "janeiro.txt")Código antigo. Funciona, mas devolve um texto e não tem os métodos do Path
"loja" + "/" + "janeiro.txt"Evite: é fácil esquecer ou dobrar a barra, e no Windows o separador é outro
Python mais antigo

No Python 3.13 (o do Debian 13), o type() de um caminho aparece como <class 'pathlib._local.PosixPath'>, com um _local no meio. É só o lugar onde a classe mora por dentro; o uso é idêntico.


Quando dá errado

Ler um arquivo que não existe: FileNotFoundError
from pathlib import Path

arquivo = Path("loja") / "precos.txt"
texto = arquivo.read_text(encoding="utf-8")
print(texto)
$ python3 ler_falta.py
Traceback (most recent call last):
  File "/home/ana/ler_falta.py", line 4, in <module>
    texto = arquivo.read_text(encoding="utf-8")
  File "/usr/lib/python3.14/pathlib/__init__.py", line 788, in read_text
    with self.open(mode='r', encoding=encoding, errors=errors, newline=newline) as f:
         ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/pathlib/__init__.py", line 772, in open
    return io.open(self, mode, buffering, encoding, errors, newline)
           ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'loja/precos.txt'

Um traceback comprido, mas só a primeira e a última parte interessam:

  • File "/home/ana/ler_falta.py", line 4: o problema começou na linha 4 do seu programa, o read_text.
  • As duas partes do meio (/usr/lib/python3.14/pathlib/…) são o caminho que o erro fez dentro do pathlib: o read_text chamou o open, que chamou o io.open. Não é ali que você conserta.
  • FileNotFoundError: [Errno 2] No such file or directory: 'loja/precos.txt': "arquivo não encontrado: não existe esse arquivo ou pasta". O [Errno 2] é o número que o sistema dá para esse erro.

Como consertar: confira o nome (era produtos.txt?) e a pasta atual; ou pergunte antes com if arquivo.exists():; ou trate o erro com try/except FileNotFoundError (aula try e except).

Barra entre dois textos: TypeError
caminho = "loja" / "produtos.txt"
print(caminho)
$ python3 barra_texto.py
Traceback (most recent call last):
  File "/home/ana/barra_texto.py", line 1, in <module>
    caminho = "loja" / "produtos.txt"
              ~~~~~~~^~~~~~~~~~~~~~~~
TypeError: unsupported operand type(s) for /: 'str' and 'str'

"Tipos de operando não suportados para /: str e str." O ^ embaixo aponta para a barra. A barra só vira "entrar na pasta" quando pelo menos um dos lados é um Path; entre dois textos, ela é a divisão, e texto não se divide. Como consertar: comece com um Path: Path("loja") / "produtos.txt".

Texto no lugar de Path: AttributeError
arquivo = "loja/produtos.txt"
print(arquivo.exists())
$ python3 texto_exists.py
Traceback (most recent call last):
  File "/home/ana/texto_exists.py", line 2, in <module>
    print(arquivo.exists())
          ^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'exists'

"Objeto str não tem o atributo exists." A variável guarda um texto, e texto não sabe perguntar ao disco nada. Como consertar: arquivo = Path("loja/produtos.txt").

Esqueceu o import: NameError
arquivo = Path("compras.txt")
print(arquivo)
$ python3 sem_import.py
Traceback (most recent call last):
  File "/home/ana/sem_import.py", line 1, in <module>
    arquivo = Path("compras.txt")
              ^^^^
NameError: name 'Path' is not defined

"O nome Path não está definido." O Path não vem pronto como o print: ele mora no módulo pathlib. Como consertar: from pathlib import Path no começo do programa.

Ler uma pasta como se fosse arquivo: IsADirectoryError
from pathlib import Path

print(Path("loja").read_text(encoding="utf-8"))
$ python3 ler_pasta.py
Traceback (most recent call last):
  File "/home/ana/ler_pasta.py", line 3, in <module>
    print(Path("loja").read_text(encoding="utf-8"))
          ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/pathlib/__init__.py", line 788, in read_text
    with self.open(mode='r', encoding=encoding, errors=errors, newline=newline) as f:
         ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/pathlib/__init__.py", line 772, in open
    return io.open(self, mode, buffering, encoding, errors, newline)
           ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IsADirectoryError: [Errno 21] Is a directory: 'loja'

"É uma pasta: 'loja'." Pasta não tem texto para ler; o que ela tem são outros arquivos. Como consertar: leia um arquivo de dentro dela (Path("loja") / "produtos.txt") ou liste o conteúdo com iterdir().

Apagar uma pasta que não está vazia
from pathlib import Path

Path("loja").rmdir()
$ python3 rmdir_cheia.py
Traceback (most recent call last):
  File "/home/ana/rmdir_cheia.py", line 3, in <module>
    Path("loja").rmdir()
    ~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.14/pathlib/__init__.py", line 1052, in rmdir
    os.rmdir(self)
    ~~~~~~~~^^^^^^
OSError: [Errno 39] Directory not empty: 'loja'

"Pasta não está vazia." Desta vez o erro é o OSError genérico, "erro do sistema operacional". Como consertar: apague primeiro o que está dentro (com unlink(), arquivo por arquivo) e só então a pasta. Para apagar uma pasta inteira com tudo dentro existe o shutil.rmtree, do módulo shutil; use com muito cuidado, porque ele não pergunta nada.

Criar uma pasta que já existe: FileExistsError

Você já viu este na seção 5: rodar Path("loja").mkdir() pela segunda vez dá FileExistsError: [Errno 17] File exists: 'loja'. Como consertar: mkdir(exist_ok=True).

Criar uma pasta dentro de outra que não existe: FileNotFoundError no mkdir
from pathlib import Path

pasta = Path("arquivo_morto") / "2026"
pasta.mkdir()
$ python3 sem_parents.py
Traceback (most recent call last):
  File "/home/ana/sem_parents.py", line 4, in <module>
    pasta.mkdir()
    ~~~~~~~~~~~^^
  File "/usr/lib/python3.14/pathlib/__init__.py", line 1012, in mkdir
    os.mkdir(self, mode)
    ~~~~~~~~^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'arquivo_morto/2026'

Parece estranho: "não existe" é justamente o que você quer criar! Mas o que falta é a pasta de cima, arquivo_morto: o mkdir() sozinho cria só o último pedaço. Como consertar: mkdir(parents=True).

Missão: o programa quer criar arquivo_morto/2026 de uma vez, mas a pasta arquivo_morto ainda não existe. Rode, leia o erro e conserte com a opção certa do mkdir.

from pathlib import Path

pasta = Path("arquivo_morto") / "2026"
pasta.mkdir()
print("Pasta criada:", pasta.name, "é pasta?", pasta.is_dir())
from pathlib import Path

pasta = Path("arquivo_morto") / "2026"
pasta.mkdir(parents=True)
print("Pasta criada:", pasta.name, "é pasta?", pasta.is_dir())

Referência rápida

EscritaO que faz
from pathlib import PathTraz o Path para o programa
Path("loja")Cria um caminho (não mexe no disco)
p / "vendas" / "jan.txt"Junta pedaços: um caminho dentro do outro
p.name, p.stem, p.suffixNome com extensão, nome sem extensão, extensão
p.parent, p.partsA pasta de cima; todos os pedaços numa tupla
Path.cwd(), Path.home(), p.absolute()Pasta atual; pasta pessoal; caminho completo
p.exists(), p.is_file(), p.is_dir()Existe? É arquivo? É pasta?
p.mkdir(parents=True, exist_ok=True)Cria a pasta (e as do meio), sem reclamar se já existir
p.read_text(encoding="utf-8")Lê o arquivo inteiro num texto
p.write_text(texto, encoding="utf-8")Grava o texto, apagando o conteúdo antigo
p.open(…)O mesmo que open(p, …)
sorted(p.iterdir())O que está direto dentro da pasta, em ordem
sorted(p.glob("*.txt"))Os nomes que combinam com o molde, direto na pasta
sorted(p.rglob("*.txt"))…na pasta e em todas as subpastas
p.unlink(missing_ok=True)Apaga o arquivo (para sempre)
p.rmdir()Apaga a pasta, se estiver vazia
str(p)O caminho como texto
MensagemCausa provável
FileNotFoundError: [Errno 2] No such file or directoryArquivo (ou pasta de cima) não existe: nome errado, pasta atual errada, faltou parents=True
FileExistsError: [Errno 17] File existsmkdir() numa pasta que já existe: use exist_ok=True
IsADirectoryError: [Errno 21] Is a directoryTentou ler uma pasta como se fosse arquivo
OSError: [Errno 39] Directory not emptyrmdir() numa pasta com coisas dentro
TypeError: unsupported operand type(s) for /: 'str' and 'str'Barra entre dois textos: comece com Path(…)
AttributeError: 'str' object has no attribute 'exists'A variável é um texto, não um Path
NameError: name 'Path' is not definedFaltou from pathlib import Path

Exercícios

1. Juntando os pedaços

Complete para montar o caminho loja/clientes.txt:

arquivo = Path("loja") "clientes.txt"

2. A extensão

Para arquivo = Path("vendas/notas.csv"), o que mostra print(arquivo.suffix)?

3. Criar sem reclamar

Complete para criar loja/vendas/2027, inclusive as pastas do meio, sem erro se já existir:

Path("loja", "vendas", "2027").mkdir(, exist_ok=True)

4. A pasta atual não tem nenhum agenda.txt. O que acontece com p = Path("agenda.txt")?

5. A pasta loja tem produtos.txt e a subpasta vendas, com janeiro.txt. O que sorted(Path("loja").glob("*.txt")) encontra?

6. Qual linha dá TypeError?

Missão final: só os arquivos de texto

Missão: o começo do programa monta uma pasta loja com quatro coisas dentro. Do jeito que está, ele lista tudo. Troque o iterdir() por um glob que pegue só os .txt, e a última linha deve contar quantos são: 2 arquivos .txt.

from pathlib import Path

# Montando a pasta da loja (não precisa mexer aqui)
loja = Path("loja")
(loja / "fotos").mkdir(parents=True, exist_ok=True)
(loja / "produtos.txt").write_text("café\n", encoding="utf-8")
(loja / "clientes.txt").write_text("Bia\n", encoding="utf-8")
(loja / "notas.csv").write_text("nome;nota\n", encoding="utf-8")

# A partir daqui é com você
achados = sorted(loja.iterdir())
for arquivo in achados:
    print(arquivo)
print(len(achados), "arquivos .txt")
from pathlib import Path

# Montando a pasta da loja (não precisa mexer aqui)
loja = Path("loja")
(loja / "fotos").mkdir(parents=True, exist_ok=True)
(loja / "produtos.txt").write_text("café\n", encoding="utf-8")
(loja / "clientes.txt").write_text("Bia\n", encoding="utf-8")
(loja / "notas.csv").write_text("nome;nota\n", encoding="utf-8")

# A partir daqui é com você
achados = sorted(loja.glob("*.txt"))
for arquivo in achados:
    print(arquivo)
print(len(achados), "arquivos .txt")

Repare nos parênteses em (loja / "fotos").mkdir(…): primeiro a barra monta o caminho, depois o mkdir age sobre ele. Sem os parênteses, o Python tentaria fazer "fotos".mkdir(), e texto não tem mkdir.


Resumo

  • Um caminho é o endereço de um arquivo ou pasta. from pathlib import Path e Path("loja") criam um, sem mexer no disco.
  • A barra / entre um Path e um texto junta pedaços: Path("loja") / "vendas" / "janeiro.txt", com o separador certo em qualquer sistema. Entre dois textos, ela dá TypeError.
  • name, stem, suffix, parent leem pedaços do endereço (sem parênteses).
  • exists(), is_file(), is_dir() perguntam ao disco.
  • mkdir(parents=True, exist_ok=True) cria a pasta e as do meio, sem reclamar se já existir.
  • read_text() e write_text() leem e gravam o arquivo inteiro numa linha; sempre com encoding="utf-8".
  • iterdir() lista a pasta; glob("*.txt") procura direto nela; rglob desce às subpastas. Use sorted() para ter ordem.
  • unlink() apaga um arquivo para sempre; rmdir() só apaga pasta vazia.
  • No traceback, procure a última linha que é do seu programa; as de /usr/lib/python3.14/ são de dentro do Python.