Curso de Python / Usar pathlib para caminhos, pastas e busca de arquivos

pathlib.Path representa caminhos de arquivos e pastas e permite combinar suas partes conforme o sistema operacional. Um caminho relativo começa no diretório de trabalho do processo, que pode ser diferente da pasta onde o script está salvo.

Combinar caminhos e escolher uma pasta de referência

A expressão Path("data") / "expenses.csv" constrói um caminho usando o operador /, sem precisar concatenar barras manualmente. O resultado é um objeto de caminho: apenas criá-lo não cria a pasta nem o arquivo. Operações como mkdir() e write_text() é que acessam e alteram o sistema de arquivos.

Path.cwd() informa o diretório de trabalho atual. Dentro de um script, Path(__file__).resolve().parent pode indicar a pasta do próprio arquivo. Em um console interativo ou em certos ambientes de notebook, __file__ pode não existir. Defina qual referência faz parte do contrato do programa em vez de tratar essas duas pastas como equivalentes.

Essa escolha complementa a distinção entre execução de pacotes e localização dos arquivos de dados. Um programa pode localizar seus módulos corretamente e ainda gravar dados em outro lugar porque foi iniciado com um diretório de trabalho diferente.

Criar e inspecionar um arquivo de prática

Use uma pasta nova e separada para este exercício. O programa cria lab-data/expenses.csv sob o diretório de trabalho e substitui o conteúdo desse arquivo se ele já existir. Antes de repetir a execução, confirme que esse caminho contém somente dados descartáveis da prática.

Salve o código completo em paths.py, com codificação UTF-8. Abra o terminal nessa pasta, selecione o ambiente virtual se houver e execute python paths.py. Em macOS ou Ubuntu sem ambiente virtual, use python3 paths.py quando esse for o nome do interpretador. O módulo pathlib pertence à biblioteca padrão, sem instalação externa.

from pathlib import Path

base = Path("lab-data")
base.mkdir(exist_ok=True)
path = base / "expenses.csv"
path.write_text("name,amount\nlunch,8000\n", encoding="utf-8")
print(path.name, path.suffix, path.stem)
print(path.is_file(), base.is_dir())
print(sorted(p.name for p in base.glob("*.csv")))

Numa pasta de prática inicialmente vazia, o resultado esperado é:

expenses.csv .csv expenses
True True
['expenses.csv']

mkdir(exist_ok=True) permite que lab-data já seja uma pasta existente; se houver um arquivo comum com esse nome, a operação falha. O caminho path é formado dentro dela. write_text() grava e fecha o arquivo usando UTF-8; o texto contém um cabeçalho name,amount e uma linha lunch,8000. lunch é um nome de despesa de exemplo, correspondente a almoço.

name é o nome final completo, suffix é o último sufixo, aqui .csv, e stem é o nome sem esse último sufixo. is_file() e is_dir() verificam o tipo do caminho; a última impressão lista os nomes que correspondem a *.csv, em ordem. Se já houver outros itens com esse sufixo, a última linha poderá conter mais nomes.

Interpretar buscas e verificações de existência

base.glob("*.csv") procura correspondências diretamente em base; base.rglob("*.csv") inclui a busca em subpastas. Um padrão de nome pode corresponder também a uma pasta chamada, por exemplo, archive.csv. Quando só arquivos forem aceitáveis, filtre os resultados com is_file(). Não dependa da ordem de enumeração: ordenar explicitamente os nomes deixa a apresentação previsível.

Uma verificação como exists() é uma observação, não uma reserva do caminho. Entre verificar e ler ou escrever, outro processo pode mudar o arquivo. O programa ainda precisa tratar falhas relevantes e definir sua política de sobrescrita; verificar existência antes não elimina erros de acesso ou concorrência.

A extensão também é apenas parte do nome: terminar em .csv não comprova que o conteúdo tem o formato esperado. Para este exemplo, abra o arquivo com um editor compatível com UTF-8 e confirme suas duas linhas. Num programa de importação, seria necessário ler e validar o conteúdo, não apenas selecionar pelo sufixo.

Um destino como Path("out.txt") é relativo ao diretório de trabalho. Para indicar um arquivo ao lado do script, use como referência Path(__file__).resolve().parent dentro de um script que disponibilize __file__. Antes de escrever, inspecione o destino resolvido; isso esclarece a localização, mas não concede permissões nem garante uma escrita bem-sucedida. A documentação de pathlib e operações com caminhos detalha esses métodos.

Comparar nomes e diretórios sem perder a localização dos dados

  1. Na pasta de prática, execute o programa e confira o conteúdo de lab-data/expenses.csv. Acrescente temporariamente print(Path.cwd()) e print(path.resolve()) ao fim do arquivo para identificar a pasta de trabalho e o destino absoluto.
  2. Troque somente o nome expenses.csv na atribuição a path por costs.csv. A primeira linha da saída passa a costs.csv .csv costs. O arquivo anterior não é renomeado nem removido: a busca agora pode mostrar ['costs.csv', 'expenses.csv']. Volte ao nome original após comparar.
  3. Crie uma segunda pasta descartável, abra o terminal nela e execute paths.py por seu caminho absoluto, colocando-o entre aspas se contiver espaços. As impressões de diagnóstico mostram a segunda pasta e um novo lab-data sob ela. O script permanece na primeira pasta; somente o diretório de trabalho mudou.
  4. Retorne à pasta inicial, remova as duas impressões de diagnóstico e confirme as linhas originais, considerando os arquivos adicionais que você criou na comparação. Para organizar a prática, confira os caminhos absolutos e remova manualmente somente os arquivos descartáveis que acabou de produzir; não apague uma árvore de pastas sem verificar seu conteúdo.

Se um nome de caminho vier de entrada externa, considere componentes como .., caminhos absolutos e links simbólicos antes de permitir acesso a uma pasta restrita. Comparar apenas prefixos de texto não demonstra que o destino está contido nela: nomes de pastas diferentes podem começar com as mesmas letras. Uma verificação deve trabalhar com a relação entre caminhos resolvidos e considerar que o sistema de arquivos ainda pode mudar entre a verificação e a operação.