06 janeiro 2023

Manipulando caminhos (path) e arquivos no Python moderno

Uma atividade comum no desenvolvimento de software com Python é a manipulação de arquivos e caminhos do sistema operacional. Seja para leitura de um arquivo ou a escrita do mesmo em qualquer que seja o caminho destino. Isso não é complicado no Python com a ajuda da biblioteca os e a instrução open, por exemplo. Porém podemos acabar tendo que descrever em mais linhas que o necessário em versões mais modernas do Python ou utilizando bibliotecas "pobre" de recursos para este fim. Tomemos como exemplo um trecho de código comum em muitos programas escritos em Python (2 ou 3). O objetivo deste pequeno trecho de código é ler o arquivo de configuração do git, se existir, caso contrário não retorna nada:

import os

git_config = os.path.join(os.path.expanduser('~'), '.gitconfig')

if os.path.exists(git_config):
    with open(git_config, 'r') as raw_file:
        print(raw_file.read())

É um código funcional e cumpre seu objetivo. Mas existem formas "melhores" de descrever essa mesma atividade, em menos linhas, sem truques de abertura ou fechamento de arquivos e com recursos nativos da linguagem.

A partir da versão >= 3.4, Python introduziu o módulo pathlib. Com o principal e único objetivo de fazer manipulações de caminhos e arquivos de forma genérica e compatível com diferentes sistemas operacionais. Além de não retornar uma simples string, como é o caso do módulo os.path. o pathlib retorna um objeto Path (se for Unix PosixPath se for Windows WindowsPath). Além permitir uma sintaxe mais expressiva em relação aos caminhos, já que permite o uso de / (barras) como separador o módulo conta com recursos para leitura e escrita sem a necessidade do statement open.

import pathlib

git_config = pathlib.Path.home() / '.gitconfig'

if git_config.exists():
    print(git_config.read_text())

É possível também fazer a escrita de forma mais simples e sem a necessidade do uso do gerenciador de contexto ou fechamento de arquivos de forma explicita:

import pathlib

my_file = pathlib.Path('/tmp') / 'my_file.txt'
content = 'content file with pathlib module'

my_file.write_text(content)