Voltar ao Glossario
Glossario Python

Pathlib: O que É e Como Funciona | Python Brasil

Domine pathlib em Python: manipulacao de caminhos orientada a objetos, leitura de arquivos, glob, criacao de diretorios e boas praticas modernas.

O que e Pathlib?

Pathlib e o modulo da biblioteca padrao do Python (desde o Python 3.4) que oferece uma interface orientada a objetos para manipulacao de caminhos de arquivos e diretorios. Em vez de trabalhar com strings e funcoes espalhadas pelo modulo os.path, pathlib centraliza tudo na classe Path, tornando o codigo mais legivel, seguro e Pythonico.

A classe Path automaticamente usa PosixPath em sistemas Unix/macOS e WindowsPath no Windows, lidando com as diferencas de separadores de caminho de forma transparente.

Criando Caminhos

from pathlib import Path

# Caminho a partir de string
arquivo = Path('dados/relatorio.csv')
pasta = Path('/home/usuario/projetos')

# Diretorio atual
atual = Path.cwd()
print(atual)  # /home/usuario/meu_projeto

# Diretorio home do usuario
home = Path.home()
print(home)  # /home/usuario

# Concatenando caminhos com operador /
projeto = Path.home() / 'projetos' / 'minha_api'
config = projeto / 'config' / 'settings.json'
print(config)  # /home/usuario/projetos/minha_api/config/settings.json

# A partir de __file__ (caminho do script atual)
BASE_DIR = Path(__file__).resolve().parent
DATA_DIR = BASE_DIR / 'data'

Propriedades do Caminho

from pathlib import Path

arquivo = Path('/home/usuario/projetos/app/main.py')

print(arquivo.name)       # 'main.py'
print(arquivo.stem)       # 'main'
print(arquivo.suffix)     # '.py'
print(arquivo.suffixes)   # ['.py']
print(arquivo.parent)     # /home/usuario/projetos/app
print(arquivo.parents[0]) # /home/usuario/projetos/app
print(arquivo.parents[1]) # /home/usuario/projetos
print(arquivo.parts)      # ('/', 'home', 'usuario', 'projetos', 'app', 'main.py')

# Para arquivos com multiplas extensoes
compactado = Path('dados.tar.gz')
print(compactado.suffixes)  # ['.tar', '.gz']
print(compactado.stem)      # 'dados.tar'

# Modificando partes do caminho
novo = arquivo.with_name('utils.py')
print(novo)  # /home/usuario/projetos/app/utils.py

outro = arquivo.with_suffix('.txt')
print(outro)  # /home/usuario/projetos/app/main.txt

renomeado = arquivo.with_stem('app')
print(renomeado)  # /home/usuario/projetos/app/app.py

Verificacoes e Informacoes

from pathlib import Path

caminho = Path('meu_arquivo.py')

# Verificacoes de existencia e tipo
print(caminho.exists())      # True/False
print(caminho.is_file())     # True se e arquivo
print(caminho.is_dir())      # True se e diretorio
print(caminho.is_symlink())  # True se e link simbolico
print(caminho.is_absolute()) # True se caminho e absoluto

# Informacoes do arquivo
if caminho.exists():
    stat = caminho.stat()
    print(f'Tamanho: {stat.st_size} bytes')
    print(f'Modificado: {stat.st_mtime}')

    # Tamanho legivel
    tamanho = caminho.stat().st_size
    for unidade in ['B', 'KB', 'MB', 'GB']:
        if tamanho < 1024:
            print(f'{tamanho:.1f} {unidade}')
            break
        tamanho /= 1024

# Resolver caminho relativo para absoluto
absoluto = Path('relativo/caminho').resolve()
print(absoluto)

Leitura e Escrita de Arquivos

from pathlib import Path

arquivo = Path('dados.txt')

# Escrever texto
arquivo.write_text('Ola, Python Brasil!\nSegunda linha.', encoding='utf-8')

# Ler texto
conteudo = arquivo.read_text(encoding='utf-8')
print(conteudo)

# Escrever bytes
Path('imagem.bin').write_bytes(b'\x89PNG\r\n')

# Ler bytes
dados = Path('imagem.bin').read_bytes()

# Abrir com context manager (para leitura incremental)
with Path('grande.txt').open('r', encoding='utf-8') as f:
    for linha in f:
        print(linha.strip())

# Adicionar conteudo (append)
with Path('log.txt').open('a', encoding='utf-8') as f:
    f.write('Nova entrada de log\n')

Listagem e Busca de Arquivos

from pathlib import Path

projeto = Path('.')

# Listar conteudo de um diretorio
for item in projeto.iterdir():
    tipo = 'DIR' if item.is_dir() else 'ARQ'
    print(f'[{tipo}] {item.name}')

# Glob — busca com padrao
for py in projeto.glob('*.py'):
    print(py)

# Glob recursivo
for py in projeto.rglob('*.py'):
    print(py)

# Encontrar todos os arquivos de teste
testes = list(projeto.rglob('test_*.py'))
print(f'Encontrados {len(testes)} arquivos de teste')

# Filtrar por extensao
imagens = list(projeto.rglob('*.png')) + list(projeto.rglob('*.jpg'))

# Listar apenas diretorios
subdirs = [d for d in projeto.iterdir() if d.is_dir() and not d.name.startswith('.')]

Criar e Manipular Diretorios

from pathlib import Path

# Criar diretorio
Path('nova_pasta').mkdir(exist_ok=True)

# Criar diretorios intermediarios
Path('a/b/c/d').mkdir(parents=True, exist_ok=True)

# Remover arquivo
Path('temporario.txt').unlink(missing_ok=True)

# Remover diretorio vazio
Path('pasta_vazia').rmdir()

# Para remover diretorio com conteudo, use shutil
import shutil
shutil.rmtree('pasta_com_conteudo', ignore_errors=True)

# Renomear / mover
Path('antigo.txt').rename('novo.txt')
Path('arquivo.txt').rename(Path('outra_pasta') / 'arquivo.txt')

# Copiar (pathlib nao tem copy, use shutil)
shutil.copy2('origem.txt', 'destino.txt')

Padroes Praticos

from pathlib import Path

# Garantir que diretorio de saida existe
def salvar_resultado(dados: str, caminho: Path):
    caminho.parent.mkdir(parents=True, exist_ok=True)
    caminho.write_text(dados, encoding='utf-8')

# Gerar nome unico para arquivo
def nome_unico(caminho: Path) -> Path:
    if not caminho.exists():
        return caminho
    contador = 1
    while True:
        novo = caminho.with_stem(f'{caminho.stem}_{contador}')
        if not novo.exists():
            return novo
        contador += 1

# Calcular tamanho total de um diretorio
def tamanho_diretorio(caminho: Path) -> int:
    return sum(f.stat().st_size for f in caminho.rglob('*') if f.is_file())

total = tamanho_diretorio(Path('.'))
print(f'Tamanho total: {total / 1024 / 1024:.1f} MB')

Erros Comuns

O erro mais frequente e usar concatenacao de strings ('/pasta' + '/' + 'arquivo') em vez do operador / do pathlib, criando caminhos que quebram entre sistemas operacionais. Outro erro e esquecer de chamar resolve() para obter o caminho absoluto, especialmente ao comparar caminhos. Tambem e comum nao verificar exists() antes de operacoes que exigem que o arquivo exista, e esquecer encoding='utf-8' ao ler ou escrever arquivos com caracteres acentuados.

Boas Praticas

Use Path em vez de os.path para todo codigo novo. Use o operador / para concatenar caminhos. Sempre especifique encoding ao ler e escrever texto. Use exist_ok=True em mkdir() e missing_ok=True em unlink(). Defina constantes BASE_DIR e DATA_DIR no inicio do projeto. Use rglob() para busca recursiva em vez de combinacoes de os.walk().

Quando Usar

Pathlib deve ser usado em qualquer codigo Python moderno que manipule caminhos de arquivos e diretorios. E a abordagem recomendada desde o Python 3.6 e oferece integracao com a maioria das bibliotecas da biblioteca padrao que aceitam caminhos como argumentos.