---
title: "Pathlib: O que É e Como Funciona | Python Brasil"
url: "https://python.dev.br/glossario/pathlib/"
markdown_url: "https://python.dev.br/glossario/pathlib.MD"
description: "Domine pathlib em Python: manipulacao de caminhos orientada a objetos, leitura de arquivos, glob, criacao de diretorios e boas praticas modernas."
date: "2025-08-05"
author: ""
---

# 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

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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.
