Caminhos com pathlib
Esta aula explora a biblioteca pathlib do Python, focando na classe Path, operações comuns e boas práticas, além de comparar com os.path. Você aprenderá a manipular caminhos de arquivos de forma moderna, portátil e orientada a objetos.
Bem-vindo à aula sobre pathlib, a biblioteca moderna do Python para manipulação de caminhos de arquivos. Se você já usou os.path, sabe que trabalhar com caminhos pode ser trabalhoso e propenso a erros, especialmente ao lidar com diferentes sistemas operacionais. O pathlib, introduzido na versão 3.4 e aprimorado nas seguintes, oferece uma abordagem orientada a objetos que torna o código mais legível, expressivo e portátil.
Nesta aula, vamos nos aprofundar na classe Path, explorar as operações mais comuns, comparar com os.path e discutir boas práticas para que você possa adotar pathlib em seus projetos com confiança. Ao final, você terá exercícios para consolidar o conhecimento.
Path
A classe Path é o coração do pathlib. Ela representa um caminho (path) de arquivo ou diretório de forma abstrata, independente do sistema operacional. Em vez de strings simples, você trabalha com objetos que possuem métodos e propriedades úteis. Para começar, importamos a classe:
from pathlib import Path
Você pode criar um objeto Path de várias maneiras. A mais comum é passar uma string ou usar o construtor com múltiplos argumentos:
# A partir de uma string
caminho = Path('/home/usuario/documentos/arquivo.txt')
# Com partes separadas
caminho = Path('home', 'usuario', 'documentos', 'arquivo.txt')
# Caminho relativo
relativo = Path('documentos/arquivo.txt')
Uma das grandes vantagens é que os objetos Path se adaptam ao sistema operacional em uso. No Windows, por exemplo, a barra invertida é usada, mas você pode usar a barra normal (/) e o Python converte automaticamente. Isso torna seu código portátil sem esforço.
Outra característica importante é que Path é uma classe que pode ser subclassificada, mas na prática usamos as subclasses PosixPath (Linux/Mac) e WindowsPath (Windows) automaticamente. Você também pode obter o caminho atual com Path.cwd() e o caminho do home do usuário com Path.home().
Operações
O pathlib oferece uma vasta gama de operações para lidar com caminhos. Vamos explorar as mais essenciais.
Verificações e propriedades
Você pode facilmente verificar se um caminho existe, se é um arquivo ou diretório, e obter informações como nome e sufixo:
p = Path('documentos/arquivo.txt')
print(p.exists()) # True se existir
print(p.is_file()) # True se for arquivo
print(p.is_dir()) # True se for diretório
print(p.name) # 'arquivo.txt'
print(p.stem) # 'arquivo' (sem extensão)
print(p.suffix) # '.txt'
print(p.parent) # 'documentos'
Manipulação de caminhos
Para construir novos caminhos, você pode usar o operador / (divisão) para concatenar partes. Isso é muito mais limpo que usar os.path.join:
base = Path('/home/usuario')
arquivo = base / 'documentos' / 'arquivo.txt'
print(arquivo) # /home/usuario/documentos/arquivo.txt
Para obter o caminho absoluto, use resolve(), que também normaliza o caminho:
relativo = Path('documentos/arquivo.txt')
absoluto = relativo.resolve()
print(absoluto) # /home/usuario/documentos/arquivo.txt (caminho completo)
Operações de arquivo e diretório
O pathlib inclui métodos para criar, renomear, excluir e listar arquivos/diretórios. Veja alguns exemplos:
# Criar diretório (incluindo pais, se necessário)
p = Path('novo/diretorio')
p.mkdir(parents=True, exist_ok=True)
# Criar arquivo vazio
arquivo = p / 'exemplo.txt'
arquivo.touch()
# Renomear
arquivo.rename(p / 'renomeado.txt')
# Excluir arquivo
(p / 'renomeado.txt').unlink()
# Listar conteúdo de um diretório
for item in p.iterdir():
print(item)
Para ler e escrever arquivos, pathlib oferece métodos convenientes como read_text() e write_text(), que gerenciam a abertura e fechamento do arquivo:
arquivo = Path('exemplo.txt')
arquivo.write_text('Olá, mundo!')
conteudo = arquivo.read_text()
print(conteudo) # Olá, mundo!
Trabalhando com glob
O método glob() permite buscar arquivos que correspondam a um padrão, semelhante ao glob do módulo glob:
for txt in Path('.').glob('*.txt'):
print(txt)
Isso é extremamente útil para processar múltiplos arquivos de uma vez.
vs os.path
Antes do pathlib, a forma tradicional era usar o módulo os.path, que trabalha com strings. Vamos comparar as duas abordagens para entender as vantagens do pathlib.
Exemplo com os.path:
import os
caminho = os.path.join('/home/usuario', 'documentos', 'arquivo.txt')
print(os.path.basename(caminho)) # arquivo.txt
print(os.path.dirname(caminho)) # /home/usuario/documentos
print(os.path.splitext(caminho)[0]) # /home/usuario/documentos/arquivo
Exemplo equivalente com pathlib:
from pathlib import Path
caminho = Path('/home/usuario') / 'documentos' / 'arquivo.txt'
print(caminho.name) # arquivo.txt
print(caminho.parent) # /home/usuario/documentos
print(caminho.stem) # arquivo
Diferenças principais:
- Orientado a objetos:
pathlibusa objetos com métodos, enquantoos.pathusa funções que recebem strings. - Portabilidade:
pathliblida automaticamente com separadores do sistema,os.pathtambém, mas de forma menos integrada. - Legibilidade: O operador
/para concatenar é mais intuitivo queos.path.join. - Riqueza de métodos:
Pathtem métodos comoread_text(),glob(),mkdir()que emos.pathexigem chamadas adicionais aosouglob.
Embora os.path ainda seja amplamente usado e funcione bem, o pathlib é recomendado para código novo, pois é mais limpo e menos propenso a erros.
Boas práticas
Ao usar pathlib, siga estas recomendações para escrever código robusto e claro:
- Prefira
Patha strings: Sempre que você for manipular caminhos, usePathem vez de strings, a menos que esteja lidando com APIs que exijam strings (comoopen(), que aceita ambos, mas prefiraPath). - Use
/para concatenar: Em vez deos.path.join, use o operador/para construir caminhos, deixando o código mais legível. - Aproveite os métodos convenientes: Use
read_text(),write_text(),glob(),mkdir(), etc., para reduzir o boilerplate. - Trate exceções: Operações como
mkdir()podem lançarFileExistsErrorse o diretório já existir (a menos queexist_ok=True). Sempre trate ou use os parâmetros adequados. - Seja consistente: Escolha entre caminhos absolutos e relativos com base no contexto, mas documente suas escolhas.
- Evite
os.chdir(): Em vez de mudar o diretório de trabalho, use caminhos absolutos ou relativos a partir de um ponto fixo.
Um exemplo de boas práticas em um script:
from pathlib import Path
def processar_arquivos(diretorio: str):
base = Path(diretorio)
if not base.is_dir():
raise ValueError(f'{diretorio} não é um diretório válido')
for arquivo in base.glob('*.txt'):
conteudo = arquivo.read_text(encoding='utf-8')
# Processa o conteúdo...
print(f'Processado: {arquivo.name}')
Referências
- Documentação oficial do pathlib
- Real Python: Python pathlib
- Documentação do os.path
- GeeksforGeeks: pathlib module
- DataCamp: Python pathlib tutorial
- Towards Data Science: Why you should start using pathlib
Exercícios
-
Crie um objeto
Pathque represente o arquivodados.csvdentro do diretórioprojetono diretório home do usuário. Imprima o caminho absoluto.✓ Resposta:from pathlib import Path caminho = Path.home() / 'projeto' / 'dados.csv' print(caminho.resolve()) -
Escreva um código que crie o diretório
backupdentro do diretório atual, se ele não existir, e depois crie um arquivo vazio chamadobackup.txtdentro dele.✓ Resposta:from pathlib import Path backup_dir = Path('backup') backup_dir.mkdir(exist_ok=True) (backup_dir / 'backup.txt').touch() -
Dada uma lista de arquivos com extensão
.logem um diretório, escreva um script que imprima o nome de cada arquivo (sem extensão) e o tamanho em bytes.✓ Resposta:from pathlib import Path for arquivo in Path('.').glob('*.log'): tamanho = arquivo.stat().st_size print(f'{arquivo.stem}: {tamanho} bytes') -
Explique a diferença entre
Path.resolve()ePath.absolute(). Em que situação você usaria um em vez do outro?✓ Resposta:Path.resolve()retorna o caminho absoluto, resolvendo symlinks e normalizando o caminho (removendo..).Path.absolute()apenas prefixa o diretório de trabalho atual, sem resolver symlinks ou normalizar. Useresolve()quando precisar de um caminho canônico eabsolute()quando apenas precisar do caminho absoluto sem se preocupar com symlinks. -
Escreva uma função que receba um caminho de um arquivo e retorne o conteúdo do arquivo em letras maiúsculas, usando
pathlib. Se o arquivo não existir, retorne uma string vazia.✓ Resposta:from pathlib import Path def ler_em_maiusculas(caminho: str) -> str: p = Path(caminho) if p.exists() and p.is_file(): return p.read_text(encoding='utf-8').upper() return ''
Observações finais: O pathlib é uma ferramenta poderosa que simplifica a manipulação de caminhos. Ao incorporá-lo no seu dia a dia, você escreverá código mais limpo e portátil. Lembre-se de explorar a documentação oficial e praticar com projetos reais para fixar o conteúdo.