pathlib en Python: Path para rutas, glob, mkdir, iterdir y operaciones de ficheros

El módulo os.path siempre fue funcional pero verboso. Desde Python 3.4, pathlib.Path proporciona una API orientada a objetos para trabajar con rutas: los paths se combinan con el operador /, los métodos son autodescriptivos y el código resultante es más legible y portable entre sistemas operativos.

Crear y combinar paths

from pathlib import Path

# Crear paths
base = Path("/var/www/proyecto")
config = base / "config" / "settings.json"  # combinar con /
print(config)  # /var/www/proyecto/config/settings.json

# Path relativo al directorio actual
raiz = Path(".")
src = raiz / "src" / "main.py"

# Path al directorio home del usuario
home = Path.home()
print(home)  # /root (o /home/usuario)

# Path al directorio del script actual
aqui = Path(__file__).parent
print(aqui)

Componentes de un path

from pathlib import Path

p = Path("/var/www/proyecto/src/utils.py")

print(p.name)      # utils.py (nombre con extensión)
print(p.stem)      # utils (nombre sin extensión)
print(p.suffix)    # .py (extensión)
print(p.suffixes)  # ['.py'] (lista de extensiones, útil para .tar.gz)
print(p.parent)    # /var/www/proyecto/src
print(p.parents)   # [/var/www/proyecto/src, /var/www/proyecto, /var/www, /var, /]
print(p.parts)     # ('/', 'var', 'www', 'proyecto', 'src', 'utils.py')
print(p.root)      # /

# Cambiar extensión
nuevo = p.with_suffix(".txt")
print(nuevo)  # /var/www/proyecto/src/utils.txt

# Cambiar nombre
otro = p.with_name("helpers.py")
print(otro)  # /var/www/proyecto/src/helpers.py

Leer y escribir ficheros

from pathlib import Path

ruta = Path("datos.txt")

# Escribir (crea o sobreescribe)
ruta.write_text("Hola, mundonSegunda línean", encoding="utf-8")

# Leer completo
contenido = ruta.read_text(encoding="utf-8")
print(contenido)

# Bytes
ruta_bin = Path("imagen.bin")
ruta_bin.write_bytes(b"x89PNGrn")
datos = ruta_bin.read_bytes()

# Abrir con open() (también funciona con Path)
with ruta.open("a", encoding="utf-8") as f:
    f.write("Tercera línean")

mkdir, iterdir y operaciones de directorio

from pathlib import Path

# Crear directorios
directorio = Path("mi_proyecto/src/utils")
directorio.mkdir(parents=True, exist_ok=True)
# parents=True: crea intermedios si no existen
# exist_ok=True: no lanza error si ya existe

# Comprobar existencia y tipo
p = Path("mi_archivo.txt")
print(p.exists())   # True/False
print(p.is_file())  # True si es fichero
print(p.is_dir())   # True si es directorio

# Listar contenido de un directorio
directorio = Path("/tmp")
for elemento in directorio.iterdir():
    tipo = "DIR" if elemento.is_dir() else "FILE"
    print(f"[{tipo}] {elemento.name}")

# Renombrar y mover
p.rename(Path("nuevo_nombre.txt"))
p.replace(Path("/otro/directorio/fichero.txt"))  # mueve y sobreescribe si existe

# Eliminar
p.unlink(missing_ok=True)  # elimina fichero (missing_ok evita error si no existe)
directorio_vacio = Path("temporal")
directorio_vacio.rmdir()  # solo si está vacío

import shutil
shutil.rmtree(Path("directorio_completo"))  # elimina árbol completo

glob — buscar ficheros por patrón

from pathlib import Path

proyecto = Path(".")

# Buscar todos los .py en el directorio actual (no recursivo)
for py in proyecto.glob("*.py"):
    print(py.name)

# Búsqueda recursiva con **
for py in proyecto.rglob("*.py"):
    print(py)  # todos los .py en cualquier subdirectorio

# Patrones más específicos
for config in proyecto.glob("**/config*.json"):
    print(config)

# Filtrar y ordenar
archivos_py = sorted(proyecto.rglob("*.py"), key=lambda p: p.stat().st_size)
for f in archivos_py[-5:]:  # los 5 más grandes
    print(f"{f}: {f.stat().st_size:,} bytes")

Información del fichero con stat()

from pathlib import Path
from datetime import datetime

p = Path("mi_fichero.txt")
p.write_text("contenido de prueba")

info = p.stat()
print(f"Tamaño: {info.st_size} bytes")
print(f"Modificado: {datetime.fromtimestamp(info.st_mtime)}")
print(f"Creado:     {datetime.fromtimestamp(info.st_ctime)}")

Comparación con os.path

import os
from pathlib import Path

# os.path (más verboso)
ruta = os.path.join("/var/www", "proyecto", "main.py")
nombre = os.path.basename(ruta)
existe = os.path.exists(ruta)
directorio = os.path.dirname(ruta)

# pathlib (más expresivo)
ruta = Path("/var/www") / "proyecto" / "main.py"
nombre = ruta.name
existe = ruta.exists()
directorio = ruta.parent

# La diferencia se nota más en operaciones encadenadas
# os.path: os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.json")
# pathlib: Path(__file__).parent / "config.json"

La regla práctica: usa pathlib para todo código nuevo. Es más legible, más expresivo y portable entre Windows (que usa ) y Unix (que usa /) sin ningún cambio, porque Python siempre muestra el separador correcto para el sistema. El operador / para concatenar paths es especialmente útil porque hace el código leíble como una ruta real.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP