programa
Um guia abrangente para usar pathlib em Python para manipulação do sistema de arquivos
Até recentemente, a manipulação do sistema de arquivos em Python era notoriamente difícil. Os desenvolvedores frequentemente enfrentavam dificuldades com caminhos de arquivos incorretos, que eram propensos a erros porque exigiam longas cadeias de caracteres como entradas. Além disso, os desenvolvedores relataram que seu código quebrava com frequência devido a inconsistências em diferentes sistemas operacionais.
Felizmente, na versão 3.4 do Python, os desenvolvedores introduziram o módulo pathlib
na biblioteca padrão. O pathlib
oferece uma solução elegante para lidar com os caminhos do sistema de arquivos usando uma abordagem orientada a objetos há muito esperada e também garante um comportamento independente de plataforma.
Este tutorial abrangente ensinará a você os recursos do módulo pathlib
para dar suporte às suas interações diárias com o sistema de arquivos. Usando o pathlib
, você se beneficiará de fluxos de trabalho eficientes e da fácil recuperação de dados. O pathlib
amadureceu significativamente ao longo dos anos, e nós nos mantivemos atualizados para que você não precise fazer isso. Vamos começar.
Módulo Python os vs. pathlib
Antes do Python 3.4, a maneira mais tradicional de lidar com caminhos de arquivos era usar o módulo os
. Embora o módulo os
já tenha sido altamente eficaz, ele começou a mostrar sua idade.
Podemos mostrar o valor exclusivo do pathlib
considerando uma tarefa comum na ciência de dados: como encontrar todos os arquivos png
em um determinado diretório e em todos os seus subdiretórios.
Se estivéssemos usando o módulo os
, poderíamos escrever o seguinte código:
import os
dir_path = "/home/user/documents"
files = [
os.path.join(dir_path, f)
for f in os.listdir(dir_path)
if os.path.isfile(os.path.join(dir_path, f)) and f.endswith(".png")
]
Embora esse código resolva a tarefa imediata de encontrar nossos arquivos png
, ele revela várias desvantagens importantes do módulo os
. Por um lado, o código é longo e quase ilegível, o que é uma pena, considerando que essa é uma operação relativamente simples. Como segundo ponto, nosso código pressupõe o conhecimento de compreensões de lista, o que não deve ser considerado como certo. Como terceiro ponto, o código envolve operações com strings, que são propensas a erros. E, além de tudo isso, o código não é muito conciso.
Se, em vez disso, estivéssemos usando o módulo pathlib, nosso código seria muito mais simples. Como mencionamos, o site pathlib
oferece uma abordagem orientada a objetos para lidar com os caminhos do sistema de arquivos. Dê uma olhada:
from pathlib import Path
# Create a path object
dir_path = Path(dir_path)
# Find all text files inside a directory
files = list(dir_path.glob("*.png"))
Essa programação orientada a objetos organiza o código em torno de objetos e suas interações, o que resulta em um código mais modular, reutilizável e de fácil manutenção. Se você não está familiarizado com a programação orientada a objetos, vale a pena aprender com nossocurso Object-Oriented Python Programming.
Trabalhando com objetos de caminho em Python
A biblioteca pathlib
gira em torno dos chamados objetos Path
, que representam os caminhos do sistema de arquivos de forma estruturada e independente de plataforma.
No início deste tutorial, trouxemos a classe Path
do módulo pathlib
para o nosso namespace atual usando a seguinte linha de código:
from pathlib import Path
Depois de chamar a classe Path
em pathlib
, podemos criar objetos Path
de várias maneiras, inclusive a partir de cadeias de caracteres, de outros objetos Path
, do diretório de trabalho atual e do diretório inicial.
Vamos dar uma olhada em cada uma delas.
Criando objetos de caminho a partir de strings
Podemos criar um objeto Path
passando uma string que representa um caminho do sistema de arquivos para uma variável. Isso converte a representação de string do caminho do arquivo em um objeto Path
.
file_path_str = "data/union_data.csv"
data_path = Path(file_path_str)
Criando objetos de caminho a partir de outros objetos de caminho
Os objetos existentes no site Path
podem servir como blocos de construção para a criação de novos caminhos.
Fazemos isso combinando um caminho base, um diretório de dados e um nome de arquivo em um único caminho de arquivo. Devemos nos lembrar de usar uma barra sempre que apropriado para estender nossos objetos Path
.
base_path = Path("/home/user")
data_dir = Path("data")
# Combining multiple paths
file_path = base_path / data_dir / "prices.csv"
print(file_path)
'/home/user/data/prices.csv'
Criar objetos de caminho a partir do diretório de trabalho atual
Aqui, atribuímos o diretório de trabalho atual à variável cwd
usando o método Path.cwd()
. Em seguida, podemos recuperar o caminho do diretório de trabalho atual onde o nosso script está sendo executado.
cwd = Path.cwd()
print(cwd)
'/home/bexgboost/articles/2024/4_april/8_pathlib'
Criando objetos de caminho a partir do diretório de trabalho inicial
Podemos construir um caminho combinando nosso diretório pessoal com subdiretórios adicionais. Aqui estamos combinando nosso diretório pessoal com os subdiretórios "downloads" e "projetos".
home = Path.home()
home / "downloads" / "projects"
PosixPath('/home/bexgboost/downloads/projects')
Uma observação importante: A classe Path
em si não executa nenhuma operação do sistema de arquivos, como validação de caminho, criação de diretórios ou arquivos. Ele foi projetado para representar e manipular caminhos. Para interagir de fato com o sistema de arquivos (verificar a existência, ler/gravar arquivos), teremos de usar métodos especiais dos objetos Path
e, em alguns casos avançados, obter ajuda do módulo os
.
Trabalhando com componentes de caminho em Python
Os atributos de caminho de arquivo são várias propriedades e componentes de um caminho de arquivo que ajudam a identificar e gerenciar arquivos e diretórios em um sistema de arquivos. Assim como um endereço físico tem diferentes partes, como número da rua, cidade, país e código postal, um caminho de sistema de arquivos pode ser dividido em componentes menores. O site pathlib
nos permite acessar e manipular esses componentes usando atributos de caminho por meio da notação de ponto.
Trabalhando com o diretório raiz
A raiz é o diretório mais alto em um sistema de arquivos. Em sistemas do tipo Unix, ele é representado por uma barra (/
). No Windows, normalmente é uma letra de unidade seguida de dois pontos, como C:
.
image_file = home / "downloads" / "midjourney.png"
image_file.root
'/'
Trabalhando com o diretório pai
O pai contém o arquivo ou diretório atual. Ele está um nível acima em relação ao diretório ou arquivo atual.
image_file.parent
PosixPath('/home/bexgboost/downloads')
Trabalhando com o nome do arquivo
Esse atributo retorna o nome completo do arquivo, inclusive a extensão, como uma cadeia de caracteres.
image_file.name
'midjourney.png'
Trabalhando com o sufixo do arquivo
O atributo suffix retorna a extensão do arquivo, incluindo o ponto, como uma cadeia de caracteres (ou uma cadeia de caracteres vazia se não houver nenhuma extensão).
image_file.suffix
'.png'
Trabalhando com a haste do arquivo
A haste retorna o nome do arquivo sem a extensão. Trabalhar com a haste pode ser útil ao converter arquivos em diferentes formatos.
image_file.stem
'midjourney'
Observação: Em um Mac, os caminhos de arquivo diferenciam maiúsculas de minúsculas, portanto, /Users/username/Documents
e /users/username/documents
seriam diferentes.
O atributo pathlib parts
Podemos usar o atributo .parts
para dividir um objeto Path
em seus componentes.
image_file.parts
('/', 'home', 'bexgboost', 'downloads', 'midjourney.png')
O atributo pathlib parents
O atributo parents
, que retorna um gerador, transforma esses componentes em objetos Path
.
list(image_file.parents)
[PosixPath('/home/bexgboost/downloads'),
PosixPath('/home/bexgboost'),
PosixPath('/home'),
PosixPath('/')]
Operações comuns de caminho usando pathlib
Path
têm muitos métodos que permitem que você interaja de forma eficiente com os diretórios e seus conteúdos. Vamos dar uma olhada em como realizar algumas das operações mais comuns.
Diretórios de listagem
O método iterdir()
permite que você itere sobre todos os arquivos e subdiretórios em uma pasta. É particularmente útil para processar todos os arquivos em um diretório ou executar operações em cada entrada.
cwd = Path.cwd()
for entry in cwd.iterdir():
# Process the entry here
...
# print(entry)
Como iterdir()
retorna um iterador, as entradas são recuperadas sob demanda à medida que você percorre o loop.
O método is_dir()
O método is_dir()
retorna True
se o caminho apontar para um diretório e False
caso contrário.
for entry in cwd.iterdir():
if entry.is_dir():
print(entry.name)
.ipynb_checkpoints
data
images
O método is_file()
O método .is_file()
retorna True
se o caminho apontar para um arquivo e False
caso contrário.
for entry in cwd.iterdir():
if entry.is_file():
print(entry.suffix)
.ipynb
.txt
O método exists()
Como os objetos Path
representam apenas caminhos, às vezes você precisa verificar se um caminho existe usando o método .exists()
:
O método .exists() verifica se um caminho existe. Isso é útil porque os objetos Path
podem representar arquivos e diretórios que podem ou não estar realmente presentes no sistema de arquivos.
image_file.exists()
False
Criação e exclusão de caminhos
pathlib
também oferece funcionalidades para criar e excluir arquivos e diretórios. Vamos ver como.
O método mkdir()
O método mkdir()
cria um novo diretório no caminho especificado. Por padrão, ele cria o diretório no diretório de trabalho atual.
from pathlib import Path
data_dir = Path("new_data_dir")
# Create the directory 'new_data_dir' in the current working directory
data_dir.mkdir()
O método mkdir(parents=True)
O método mkdir(parents=True)
é particularmente útil quando você deseja criar uma estrutura de diretórios em que alguns diretórios pai podem não existir. A configuração de parents=True
garante que todos os diretórios pai necessários sejam criados ao longo do caminho.
sub_dir = Path("data/nested/subdirectory")
# Create 'data/nested/subdirectory', even if 'data' or 'nested' don't exist
sub_dir.mkdir(parents=True)
Lembre-se de que o site mkdir()
gera uma exceção se já existir um diretório com o mesmo nome.
Path('data').mkdir()
FileExistsError: [Errno 17] File exists: 'data'
O método unlink()
O método unlink()
exclui permanentemente um arquivo representado pelo objeto Path
. Recomenda-se que você verifique se um arquivo existe antes de executar esse método para evitar receber um erro.
to_delete = Path("data/prices.csv")
if to_delete.exists():
to_delete.unlink()
print(f"Successfully deleted {to_delete.name}")
Successfully deleted prices.csv
O método rmdir()
O método rmdir()
remove um diretório vazio. Lembre-se de que o rmdir()
só funciona para remover diretórios vazios. A maneira mais fácil de excluir um diretório não vazio é usar a biblioteca shutil ou o terminal.
empty_dir = Path("new_data_dir")
empty_dir.rmdir()
Observação: Tenha cuidado ao usar unlink()
ou rmdir()
, pois os resultados são permanentes.
Manipulação avançada de caminhos
Vamos passar para alguns conceitos avançados de manipulação de caminhos e como aplicá-los na prática usando o site pathlib
.
Caminhos relativos vs. absolutos
Começaremos entendendo as diferenças entre caminhos absolutos e relativos, pois eles aparecem com frequência.
Caminhos relativos
Os caminhos relativos especificam o local de um arquivo ou diretório em relação ao diretório atual, daí a palavra relativo. Eles são curtos e flexíveis em seu projeto, mas podem ser confusos se você mudar o diretório de trabalho.
Por exemplo, tenho uma pasta de imagens em meu diretório de trabalho atual, que tem o arquivo midjourney.png
.
image = Path("images/midjourney.png")
image
PosixPath('images/midjourney.png')
O código acima funciona agora, mas se eu mover o notebook que estou usando para um local diferente, o snippet será interrompido porque a pasta de imagens não foi movida com o notebook.
Caminhos absolutos
Os caminhos absolutos especificam o local completo de um arquivo ou diretório a partir da raiz do sistema de arquivos. Eles são independentes do diretório atual e oferecem um ponto de referência claro para qualquer usuário em qualquer lugar do sistema.
image_absolute = Path("/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png")
image_absolute
PosixPath('/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png')
Como você pode ver, os caminhos absolutos podem ser bem longos, especialmente em projetos complexos com estruturas de árvore aninhadas. Por esse motivo, a maioria das pessoas prefere caminhos relativos, que são mais curtos.
Método de resolução
pathlib
fornece métodos para converter caminhos relativos em absolutos com o método resolve()
.
relative_image = Path("images/midjourney.png")
absolute_image = relative_image.resolve()
absolute_image
PosixPath('/home/bexgboost/articles/2024/4_april/8_pathlib/images/midjourney.png')
Você também pode fazer o caminho inverso: Se tivermos um caminho absoluto, podemos convertê-lo em um caminho relativo com base em um diretório de referência.
relative_path = Path.cwd()
absolute_image.relative_to(relative_path)
PosixPath('images/midjourney.png')
Globbing
Para ilustrar o globbing, podemos voltar ao exemplo que apresentamos no início do artigo, em que escrevemos um código para localizar todos os arquivos png
em um determinado diretório.
files = list(dir_path.glob("*.png"))
pathlib
usa o módulo .glob()
incorporado para pesquisar com eficiência os arquivos que correspondem a um padrão específico em qualquer diretório. Esse módulo é muito útil ao processar arquivos com nomes ou extensões semelhantes.
O método glob funciona aceitando uma string de padrão contendo curingas como entrada e retorna um objeto gerador que produz objetos Path
correspondentes sob demanda:
-
*
: Corresponde a zero ou mais caracteres. -
?
: Corresponde a qualquer caractere único. -
[]
: Corresponde a um intervalo de caracteres entre colchetes (por exemplo, [a-z] corresponde a qualquer letra minúscula).
Para ilustrar, vamos tentar localizar todos os notebooks Jupyter em meu diretório de artigos.
articles_dir = Path.home() / "articles"
# Find all scripts
notebooks = articles_dir.glob("*.ipynb")
# Print how many found
print(len(list(notebooks)))
0
O método .glob()
não encontrou nenhum notebook, o que, à primeira vista, parece surpreendente, pois escrevi mais de 150 artigos. O motivo é que o .glob()
só pesquisa dentro do diretório fornecido, não em seus subdiretórios.
Podemos resolver isso fazendo uma pesquisa recursiva, para a qual precisamos usar o método rglob()
, que tem sintaxe semelhante:
notebooks = articles_dir.rglob("*.ipynb")
print(len(list(notebooks)))
357
Dessa vez, nosso código encontrou todos os 357 arquivos.
Trabalhar com arquivos
Como vimos, os objetos Path
representam apenas arquivos, mas não executam operações neles. No entanto, eles têm determinados métodos para operações comuns de arquivos. Veremos como usá-los nesta seção.
Leitura de arquivos
A leitura do conteúdo dos arquivos é uma operação fundamental em muitos aplicativos Python. O site pathlib
oferece métodos abreviados convenientes para a leitura de arquivos como texto ou bytes brutos.
O método read_text()
nos permite ler o conteúdo de um arquivo de texto e fechar o arquivo.
file = Path("file.txt")
print(file.read_text())
This is sample text.
No caso de arquivos binários, você pode usar o método read_bytes()
.
image = Path("images/midjourney.png")
image.read_bytes()[:10]
b'\x89PNG\r\n\x1a\n\x00\x00'
Lembre-se de que, ao usar um método read_*
, o tratamento de erros é importante:
nonexistent_file = Path("gibberish.txt")
try:
contents = nonexistent_file.read_text()
except FileNotFoundError:
print("No such thing.")
No such thing.
Gravação de arquivos
Escrever em arquivos é tão fácil quanto ler arquivos. Para gravar arquivos, temos o método write_text()
.
file = Path("file.txt")
file.write_text("This is new text.")
17
file.read_text()
'This is new text.'
Como você pode ver, o método write_text()
substitui o texto. Embora não haja modo de acréscimo para write_text()
, podemos usar read_text()
e write_text()
juntos para acrescentar texto ao final do arquivo.
old_text = file.read_text() + "\n"
final_text = "This is the final text."
# Combine old and new texts and write them back
file.write_text(old_text + final_text)
print(file.read_text())
This is new text.
This is the final text.
write_bytes()
funciona de maneira semelhante. Para ilustrar, vamos primeiro duplicar a imagem midjourney.png
com um novo nome.
original_image = Path("images/midjourney.png")
new_image = original_image.with_stem("duplicated_midjourney")
new_image
PosixPath('images/duplicated_midjourney.png')
O método with_stem()
retorna um caminho de arquivo com um nome de arquivo diferente (embora o sufixo permaneça o mesmo). Isso nos permite ler uma imagem original e gravar seu contexto em uma nova imagem.
new_image.write_bytes(original_image.read_bytes())
1979612
Renomear e mover arquivos
Além da função with_stem()
para renomear a haste de um arquivo, o site pathlib
oferece o método rename()
para você renomear de forma mais completa.
file = Path("file.txt")
target_path = Path("new_file.txt")
file.rename(target_path)
PosixPath('new_file.txt')
rename()
aceita um caminho de destino, que pode ser uma cadeia de caracteres ou outro objeto de caminho.
Para mover arquivos, você pode usar a função replace()
, que também aceita um caminho de destino:
# Define the file to be moved
source_file = Path("new_file.txt")
# Define the location to put the file
destination = Path("data/new/location")
# Create the directories if they don't exist
destination.mkdir(parents=True)
# Move the file
source_file.replace(destination / source_file.name)
PosixPath('data/new/location/new_file.txt')
Criação de arquivos em branco
pathlib
nos permite criar arquivos em branco usando o método touch
:
# Define new file path
new_dataset = Path("data/new.csv")
new_dataset.exists()
False
new_dataset.touch()
new_dataset.exists()
True
O método touch
foi originalmente criado para atualizar o tempo de modificação de um arquivo, portanto, também pode ser usado em arquivos existentes.
original_image.touch()
Quando você precisa reservar um nome de arquivo para uso posterior, mas não tem nenhum conteúdo para gravar nele no momento, podemos usar o touch para criar um espaço em branco. O método foi inspirado no comando de terminal touch do Unix.
Permissões e informações do sistema de arquivos
Como item final, aprenderemos a acessar as características do arquivo usando o método .stat()
. Se você estiver familiarizado com os
, perceberá que esse novo método tem o mesmo resultado que os.stat()
.
image_stats = original_image.stat()
image_stats
os.stat_result(st_mode=33188, st_ino=1950175, st_dev=2080, st_nlink=1, st_uid=1000, st_gid=1000, st_size=1979612, st_atime=1714664562, st_mtime=1714664562, st_ctime=1714664562)
Também podemos recuperar o tamanho do arquivo usando a notação de pontos.
image_size = image_stats.st_size
# File size in megabytes
image_size / (1024**2)
1.8879051208496094
Conclusão
A introdução do módulo pathlib
no Python 3.4 simplificou significativamente a manipulação do sistema de arquivos para os desenvolvedores. Ao oferecer uma abordagem orientada a objetos para lidar com caminhos de arquivos, o pathlib
oferece uma maneira estruturada e direta de representar os caminhos do sistema de arquivos. O pathlib
também oferece independência de plataforma, o que significa que o pathlib
lida com separadores de caminho de forma consistente em diferentes sistemas operacionais para que nosso código não seja interrompido em um novo computador. Por fim, o pathlib
oferece um vasto conjunto de métodos concisos e expressivos para operações comuns do sistema de arquivos, como vimos.
Lembre-se de que pathlib
representa uma das muitas bibliotecas integradas poderosas do Python. Ao fazer os nossos cursos Data Scientist With Python Career Track, Python Programming Skill Track e Intro to Python for Data Science, você dominará um amplo conjunto de bibliotecas integradas para se tornar um programador Python forte.
Obrigado a você por ler!

Sou um criador de conteúdo de ciência de dados com mais de 2 anos de experiência e um dos maiores seguidores no Medium. Gosto de escrever artigos detalhados sobre IA e ML com um estilo um pouco sarcástico, porque você precisa fazer algo para torná-los um pouco menos monótonos. Produzi mais de 130 artigos e um curso DataCamp, e estou preparando outro. Meu conteúdo foi visto por mais de 5 milhões de pessoas, das quais 20 mil se tornaram seguidores no Medium e no LinkedIn.
Aprenda Python com o DataCamp
curso
Writing Efficient Python Code
curso
Writing Functions in Python

blog
Uma introdução aos polares: Ferramenta Python para análise de dados em grande escala
tutorial
Tutorial do Python Excel: O guia definitivo
tutorial
Tutorial de Python

DataCamp Team
3 min
tutorial
Introdução à plotagem com Matplotlib em Python
Kevin Babitz
25 min
tutorial
Perfilamento do Pandas (ydata-profiling) em Python: Um guia para iniciantes

Satyam Tripathi
9 min