Aprende leyendo en orden

os y pathlib — Rutas de archivos y operaciones con directorios

Aprende los módulos os.path y pathlib de Python desde cero. Construye rutas independientes del SO, lista y recorre directorios recursivamente, y descompón rutas en piezas con objetos Path — todo práctico.

Dos módulos manejan rutas de archivos y directorios — el más antiguo os.path y el más nuevo y legible pathlib. Este artículo recorre la construcción de rutas independientes del SO, el listado y la travesía recursiva de directorios, y la descomposición de rutas en piezas con objetos Path, en ese orden.

os.path — Construir rutas independientes del SO

Los separadores de ruta varían según el SO. Windows usa \ (barra invertida), mientras que Linux y macOS usan /. Hardcodear `"data/sales/2024.csv"` directamente en tu código funciona en Linux y Mac, pero Windows puede leer mal la ruta en tiempo de ejecución.

Si separas las partes y se las pasas a os.path.join("data", "sales", "2024.csv"), Python elige el separador correcto al vuelo según el SO en el que esté corriendo.

os.path.join cambia los separadores según el SO
os.path.join( 'data', 'sales', '2024.csv')Linux / Macdata/sales/2024.csvWindowsdata\sales\2024.csv
El mismo código Python se expande a / en Linux / Mac y a \ en Windows. No hornees los caracteres separadores a mano — ese es el truco para mantenerse portátil.
FunciónSignificadoEjemplo
os.path.join(*parts)Une rutas con el separador del SOjoin('data', 'sales') → 'data/sales'
os.path.exists(p)Si la ruta existeTrue / False
os.path.isfile(p)Si es un archivo (no un directorio)True / False
os.path.isdir(p)Si es un directorioTrue / False
os.path.basename(p)El nombre final del archivo o carpetabasename('data/x.csv') → 'x.csv'
os.path.dirname(p)La ruta padre con la cola eliminadadirname('data/x.csv') → 'data'
os.path.splitext(p)Separa la extensiónsplitext('x.csv') → ('x', '.csv')

Construye la ruta a un archivo CSV de ventas con os.path y lee su contenido (puedes ver data/sales/2024_q1.csv y otros bajo el panel 📂 Files a la izquierda).

① Importa os y une las tres partes de ruta data / sales / 2024_q1.csv en una sola cadena con el separador del SO.

② Imprime la ruta completa tal cual.

③ Abre el data/sales/2024_q1.csv precargado con open(path, "r") e imprime las primeras tres líneas.

(Si lo ejecutas correctamente aparece la explicación abajo.)

Editor Python

Ejecutar el código para ver el resultado

Práctica 2 — Separar nombre y extensión con basename y splitext

No metas todo en una línea — asigna paso a paso a variables intermedias y separa el nombre del archivo de su extensión. basename saca el nombre final del archivo de una ruta completa y splitext divide ese nombre en una tupla (nombre, extensión).

No lo escribas en una sola línea — pasa por variables intermedias para extraer el nombre del archivo y la extensión.

① Importa os y establece path = "data/sales/2024_q1.csv".

② Saca el nombre final con os.path.basename(path), guárdalo en filename e imprímelo.

③ Usa os.path.splitext(filename) para obtener la tupla (nombre, extensión), guárdala en parts e imprímela.

Desempaqueta esa tupla en stem y suffix, e imprímelos como stem suffix separados por un espacio.

Editor Python

Ejecutar el código para ver el resultado

os.listdir y os.walk — Listado de directorios y travesía recursiva

Cuando quieres traer el contenido de una carpeta a Python, usa os.listdir para un solo nivel y os.walk para descender recursivamente en subcarpetas. os.listdir devuelve una lista de nombres (tanto archivos como subcarpetas) directamente dentro de la carpeta que especificas, mientras que os.walk recorre el subárbol entero recursivamente y produce tuplas (ruta actual, lista de nombres de subcarpetas, lista de nombres de archivos) un nivel a la vez.

Diferencia entre os.listdir y os.walk
os.listdirLista de nombresen la carpeta inmediataos.walkRecorre recursivamentetodos los niveles
os.listdir te da solo los nombres inmediatos; os.walk desciende recursivamente por todos los niveles. Elige según lo profundo que necesites ir.
import os

# Un nivel: nombres directamente bajo 'data'
print(os.listdir("data"))
# → ['sales', 'inventory']

# Recursivo: recorre todo bajo 'data'
for dirpath, dirnames, filenames in os.walk("data"):
    print(dirpath, filenames)
# → data ['sales', 'inventory'] []
#    data/sales [] ['2024_q1.csv', '2024_q2.csv']
#    data/inventory [] ['items.json']

Muestra lo que hay dentro del directorio `data/` de dos formas — primero el nivel inmediato y luego recursivamente.

① Importa os.

② Usa os.listdir("data") para listar los nombres directamente bajo `data/` en orden ordenado (envuelve con sorted para mantener el orden estable).

③ Usa os.walk("data") para recorrer data/ recursivamente e imprime una línea por nivel mostrando (ruta actual, lista de nombres de archivos) (envuelve también la lista de nombres de archivos con sorted).

Editor Python

Ejecutar el código para ver el resultado

glob — Coincidencia de patrones para recolectar archivos

Cuando quieres coger solo los archivos que coinciden con una condición — como solo archivos con extensión `.csv` — el módulo glob es el camino más corto. Escribe el objetivo como un patrón usando comodines como * (cualquier cadena) o ** (cualquier profundidad) y obtienes una lista de rutas coincidentes.

Comodines de glob
*Cualquier cadena dentrodel mismo nivel**Cruza cualquier profundidad(recursive=True)
* coincide con cualquier cadena dentro del mismo nivel, ** cruza cualquier número de niveles (requiere recursive=True).
import glob

# Archivos CSV directamente bajo data/sales
print(glob.glob("data/sales/*.csv"))
# → ['data/sales/2024_q1.csv', 'data/sales/2024_q2.csv']

# Búsqueda recursiva bajo data (** + recursive=True)
print(glob.glob("data/**/*.csv", recursive=True))
# → ['data/sales/2024_q1.csv', 'data/sales/2024_q2.csv']

El comodín ** de glob va emparejado con recursive=True

El doble asterisco en glob.glob("data/**/*.csv") es un comodín que cruza cualquier número de niveles. Pero sin recursive=True, se comporta como un * normal y no encontrará nada en carpetas más profundas. Pasa siempre ese argumento cuando quieras búsqueda recursiva.

Saca los archivos CSV en `data/sales/` de un solo golpe con glob.

① Importa glob.

② Usa glob.glob("data/sales/*.csv") para coger los CSVs bajo sales, ordena con sorted y guarda el resultado en csv_files.

③ Imprime cada ruta una a una.

④ Imprime el conteo con la forma Archivos encontrados: ◯.

Editor Python

Ejecutar el código para ver el resultado

pathlib.Path — Operaciones con rutas orientadas a objetos

Mientras que os.path era una biblioteca que manejaba las rutas como cadenas, desde Python 3.4 el enfoque recomendado es pathlib.Path, que trata las rutas en sí mismas como objetos. Construye una con Path("data/sales/2024_q1.csv") y puedes acceder a cada parte mediante atributos como .parent para la carpeta padre, .name para la pieza final, .stem para el nombre sin extensión y .suffix para la extensión.

Atributos del objeto Path
Path('data/sales/2024_q1.csv').parentPath('data/sales').name'2024_q1.csv'.stem'2024_q1'.suffix'.csv'
Desde un solo Path puedes sacar cada parte con .parent / .name / .stem / .suffix. Más fácil de leer que llamar a os.path.dirname / basename / splitext por separado.
from pathlib import Path

p = Path("data") / "sales" / "2024_q1.csv"   # Une con el operador /
print(p)               # data/sales/2024_q1.csv
print(p.parent)        # data/sales
print(p.name)          # 2024_q1.csv
print(p.stem)          # 2024_q1
print(p.suffix)        # .csv
print(p.exists())      # True

# Lee el contenido (un envoltorio sobre with open)
print(p.read_text())   # contenido del CSV

# Lista subcarpetas (equivalente a os.walk)
for sub in Path("data").rglob("*.csv"):
    print(sub)

`os.path` es basado en cadenas, `pathlib.Path` es basado en objetos — ofrecen las mismas operaciones. La tabla de abajo mapea cada tarea entre ellos.

Lo que quieresEstilo os.pathEstilo pathlib
Uniros.path.join('data', 'x.csv')Path('data') / 'x.csv'
Carpeta padreos.path.dirname(p)p.parent
Nombre del archivoos.path.basename(p)p.name
Nombre sin extensiónUsa os.path.splitext(p)[0]p.stem
Extensiónos.path.splitext(p)[1]p.suffix
Comprobar existenciaos.path.exists(p)p.exists()
Búsqueda recursivaglob.glob('**/*.csv', recursive=True)Path('.').rglob('*.csv')
Leerwith open(p) as f: f.read()p.read_text()

Elige pathlib para código nuevo

Pathlib es lo recomendado para código nuevo. Cuando APIs de bibliotecas más antiguas requieren rutas como cadena (algunos drivers de BD, por ejemplo), convierte con str(p). os.path no va a desaparecer, así que conocer ambos mapeos te deja cómodo leyendo código heredado también.

Usa pathlib.Path para manejar un CSV de ventas. En lugar de concatenar cadenas directamente, obtén el mismo resultado a través del operador y los atributos del objeto Path.

① Importa la clase Path desde pathlib.

② Construye un solo objeto Path a partir de las tres partes data / sales / 2024_q1.csv usando el operador de unión de Path (el reemplazo de os.path.join).

③ Saca el nombre sin extensión y la extensión del Path mediante acceso a atributos, e imprímelos separados por un espacio.

④ Usa un método de Path para leer el contenido del archivo como una sola cadena e imprímelo (la forma que no requiere with open(...)).

Editor Python

Ejecutar el código para ver el resultado
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1¿Cuál es la forma recomendada de construir rutas que no se rompan ni en Windows ni en Linux?

Pregunta 2¿Cuál de las siguientes es la mejor para recorrer cada nivel de una carpeta recursivamente?

Pregunta 3Dado p = Path("data/sales/2024_q1.csv"), ¿cuál es el valor de p.stem?