El módulo pathlib disponible desde Python 3.4 consta de clases que permiten representar rutas de archivos y directorios de un sistema de ficheros con la semántica adecuada para distintos sistemas operativos.
Las clases cuentan con métodos que facilitan una amplia variedad de operaciones con directorios, archivos y enlaces simbólicos; que antes eran posibles, la mayoría, recurriendo a funciones y clases de varios módulos (como os, glob, shutil y fileinput). Lo que se ha pretendido con pathlib es concentrar en un módulo las operaciones más comunes teniendo en cuenta la experiencia de los desarrolladores.
Dentro de las operaciones contempladas las hay para explorar el sistema de ficheros, comprobar la existencia de rutas; recorrer los archivos y subdirectorios de un directorio filtrando los objetos mediante el uso de patrones; obtener información de los objetos (tamaño, permisos, propietarios, etc.); crear, renombrar y borrar archivos y enlaces simbólicos; crear y borrar directorios; obtener rutas del sistema en varios formatos (Posix y URI), principalmente.
Las clases cuentan con métodos que facilitan una amplia variedad de operaciones con directorios, archivos y enlaces simbólicos; que antes eran posibles, la mayoría, recurriendo a funciones y clases de varios módulos (como os, glob, shutil y fileinput). Lo que se ha pretendido con pathlib es concentrar en un módulo las operaciones más comunes teniendo en cuenta la experiencia de los desarrolladores.
Dentro de las operaciones contempladas las hay para explorar el sistema de ficheros, comprobar la existencia de rutas; recorrer los archivos y subdirectorios de un directorio filtrando los objetos mediante el uso de patrones; obtener información de los objetos (tamaño, permisos, propietarios, etc.); crear, renombrar y borrar archivos y enlaces simbólicos; crear y borrar directorios; obtener rutas del sistema en varios formatos (Posix y URI), principalmente.
Rutas puras y concretas
Las clases de pathlib se dividen en dos grupos en función a los tipos de rutas orientadas a objetos que manejan: puras y concretas. La diferencia entre ambos tipos de clases está en que las clases para rutas puras proporcionan métodos que en realidad no acceden al sistema de ficheros y las de rutas concretas, sí.
Las rutas son inmutables y por ser únicas en cada sistema de archivos se les pueden aplicar funciones hash. Las rutas de un mismo sistema se pueden comparar y ordenar de acuerdo a la semántica empleada en cada sistema.
Cualquier ruta se representa como una cadena adaptada a las rutas propias de cada sistema de archivos y, lógicamente, se podrán utilizar con cualquier función que opere con rutas en este mismo formato.
Hay tres formas de instanciar objetos de rutas puras:
A continuación, se declaran varias rutas puras y se muestran varios ejemplos que ilustran el uso de sus métodos:
Las rutas son inmutables y por ser únicas en cada sistema de archivos se les pueden aplicar funciones hash. Las rutas de un mismo sistema se pueden comparar y ordenar de acuerdo a la semántica empleada en cada sistema.
Cualquier ruta se representa como una cadena adaptada a las rutas propias de cada sistema de archivos y, lógicamente, se podrán utilizar con cualquier función que opere con rutas en este mismo formato.
Hay tres formas de instanciar objetos de rutas puras:
- class pathlib.PurePath(*pathsegments): clase genérica que crea una instancia de ruta en función del sistema operativo: puede ser PurePosixPath o un PureWindowsPath.
- class pathlib.PurePosixPath(*pathsegments): subclase que crea una instancia de ruta para sistemas de ficheros no Windows.
- class pathlib.PureWindowsPath(*pathsegments): subclase que crea una instancia de ruta para sistemas de ficheros Windows.
A continuación, se declaran varias rutas puras y se muestran varios ejemplos que ilustran el uso de sus métodos:
import os
from pathlib import PurePath, PurePosixPath, PureWindowsPath
# Declarar rutas puras
ruta1 = PurePath('home/usuario')
ruta2 = PurePath('c:\\windows')
ruta3 = PurePosixPath('home/Usuario')
ruta4 = PureWindowsPath('C:\\WINDOWS')
# Imprimir las rutas
print(ruta1) # home/usuario
print(ruta2) # c:\windows
print(ruta3) # home/Usuario
print(ruta4) # C:\WINDOWS
# Las rutas son cadenas de un tipo especial
print(type(ruta1)) #
print(type(ruta2)) #
print(type(ruta3)) #
print(type(ruta4)) #
# Las rutas se pueden comparar ...
print(ruta1 == ruta3) # False
print(ruta2 == ruta4) # True (en Windows)
print(ruta2 in [ruta4]) # True (en Windows)
print(PureWindowsPath('c:\\windows') > ruta4) # False
if os.name != 'posix':
print(ruta2 > ruta4) # False (en Win); Error (en No Win)
# Una ruta se representa como una cadena adaptada a
# las rutas propias de cada sistema de archivos
ruta5 = PurePath('/var/www/index.html')
ruta6 = PureWindowsPath('c:/Program Files')
print(ruta5) # /var/www/index.html
print(ruta6) # c:\Program Files
# Obtener por separado en una tupla todas las partes de una ruta
print(ruta5.parts) # ('/', 'var', 'www', 'index.html')
print(ruta6.parts) # ('c:\\', 'Program Files')
# Obtener la unidad (si existe) de una ruta
print(ruta5.drive) # ''
print(ruta6.drive) # 'c:'
# Obtener la raíz de una ruta. Válido para rutas UNC
print(ruta5.root) # '/'
print(ruta6.root) # '\'
# Obtener la raíz y la ruta ¡de una vez!
print(ruta5.anchor) # '/'
print(ruta6.anchor) # 'c:\'
# Obtener los ancestros de una ruta
print(ruta5.parents) #
print(len(ruta5.parents)) # Número de ancestros: 3
print(ruta5.parents[0]) # /var/www
print(ruta5.parents[1]) # /var
print(ruta5.parents[2]) # /
# Obtener el ancestro ineidato o padre de una ruta
print(ruta5.parent) # /var/www
print(ruta6.parent) # c:\
# Obtener nombre y extensión/es de archivos
print(ruta5.name) # index.html
print(ruta5.suffix) # .html
print(ruta5.suffixes) # ['.html']
print(ruta5.stem) # index
# Obtener rutas en formato POSIX y URI
print(ruta6.as_posix()) # c:/Program Files
print(ruta6.as_uri()) # file:///c:/Program%20Files
# Obtener si una ruta es absoluta: si tiene raíz o unidad
print(ruta5.is_absolute()) # True
print(ruta6.is_absolute()) # True
# Combinar rutas
print(ruta6.joinpath('Lupa')) # c:\Program Files\Lupa
print(ruta6) # c:\Program Files
# Comprobar si un patrón existe en una ruta
print(ruta5.match('*.html')) # True
print(ruta5.match('var/*.html')) # False
# Obtener la ruta relativa (si es posible)
print(ruta5.relative_to('/var')) # www/index.html
print(ruta5.relative_to('/var/www')) # index.html
# A partir de una ruta obtener otra ruta cambiando
# nombre completo de archivo o extensión (si es posible)
print(ruta5.with_name('imagen.jpg')) # /var/www/imagen.jpg
print(ruta5.with_suffix('.htm')) # /var/www/index.htm
Por otra parte, los objetos de ruta concreta pertenecen a subclases de las clases de rutas puras. Estas subclases además de ofrecer las operaciones proporcionadas por las clases de las que descienden cuentan con métodos para instancias de rutas que hacen llamadas al sistema. Hay tres formas de instanciar estos objetos:
A continuación se declaran varias rutas concretas y se ofrecen varios ejemplos que muestran el uso de sus métodos:
- class pathlib.Path(*pathsegments): es una subclase de la clase PurePath que crea una instancia de ruta concreta en función del sistema operativo: puede ser PosixPath o WindowsPath.
- class pathlib.PosixPath(*pathsegments): es una subclase de la clase PurePosixPath que crea una instacia de ruta concreta para sistemas de ficheros no Windows.
- class pathlib.WindowsPath(*pathsegments): es una subclase de la clase PureWindowsPath que crea una instancia de ruta concreta para sistemas de ficheros Windows.
A continuación se declaran varias rutas concretas y se ofrecen varios ejemplos que muestran el uso de sus métodos:
from pathlib import Path, PosixPath, WindowsPath
# Declarar rutas concretas
ruta1 = Path('home/usuario')
ruta2 = Path('c:\\windows')
ruta3 = PosixPath('home/Usuario')
ruta4 = WindowsPath('C:\\WINDOWS') # Error en Linux
# Imprimir las rutas
print(ruta1) # home/usuario
print(ruta2) # c:\windows
print(ruta3) # home/Usuario
print(ruta4) # C:\WINDOWS
# Las rutas son cadenas de un tipo especial ...
print(type(ruta1)) #
print(type(ruta2)) #
print(type(ruta3)) #
print(type(ruta4)) #
# Obtener ruta del directorio actual de trabajo
print(Path.cwd()) # /home/usuario/Directorio
# Obtener la ruta del directorio de usuario actual
print(Path.home()) # /home/usuario
# Obtener información del directio o del archivo
# Obtener tamaño en bytes
print(Path('/etc/os-release').stat().st_size) # 386
# Obtener tiempo de modificación (expresado en segundos)
print(Path('/etc/os-release').stat().st_mtime) # 1534722298.0
# Para enlaces simbólicos: lstat()
# Cambiar los atributos y/o permisos del directorio o del archivo
Path('/home/usu1/imagen1.png').chmod(0o666)
# Para enlaces simbólicos: lchmod()
# Comprobar si existe el archivo o directorio
print(Path('/etc/os-release').exists()) # True
# Expandir la ruta añadiendo la ruta 'home' del usuario actual
print(Path('~/bashrc').expanduser()) # /home/usuario/bashrc
# Obtener de la ruta una lista con los archivos del patrón
archivos = Path('/home/usu1/Descargas').glob('*.pdf')
for archivo in archivos:
print(archivo)
# Otros patrones:
# '*/*.pdf' Obtener del directorio con 1 nivel de profundidad
# '**/*.pdf' Obtener del directorio actual y sus subdirectorios
# El patrón '**/*.pdf' es equivalente a rglob('*.pdf')
# Obtener nombre del grupo propietario
print(Path('/etc/os-release').group()) # root
# Conocer si una ruta es un directorio o un enlace simbólico
# que apunta a un directorio existente
print(Path('/etc/os-release').is_dir()) # False
# Conocer si una ruta es un fichero o un enlace simbólico
# que apunta a un fichero existente
print(Path('/etc/os-release').is_file()) # True
# Conocer si una ruta es un enlace simbólico
print(Path('/etc/resolv.conf').is_symlink()) # True
# Conocer si la ruta es un punto de montaje.
# No implementado para windows. Nuevo en Python 3.7
print(Path('/media/usuario').is_mount()) # True
# Obtener iterador con objetos contenidos en un directorio
for elemento in Path('/home/usu1/Descargas').iterdir():
print(elemento) # Lista ficheros y directorios
# Crear un directorio (si no existe)
Path('/home/u1/bd').mkdir(mode=0o777, parents=False, exist_ok=True)
# Si parents=True creará los directorios padres que falten
# en el camino
# Si exist_ok=True y el directorio a crear existe se
# omitirá mensaje de error
# Abrir un archivo para leer y/o escribir
with Path('/etc/os-release').open(mode='r') as archivo:
for linea in archivo:
print(linea.strip())
# Leer y escribir de/en un archivo de texto
archivo = Path('secreto.txt')
archivo.write_text('Este archivo guarda un gran secreto')
print(archivo.read_text())
# Leer y escribir de/en un archivo en formato binario
archivo = Path('secreto.dat')
archivo.write_bytes(b'Este archivo guarda un gran secreto')
print(archivo.read_bytes())
# Conocer el propietario de un archivo
print(Path('/etc/resolv.conf').owner()) # root
# Renombrar un archivo o un directorio
Path('/home/usu1/imagen1.png').rename('/home/usu1/imagen2.png')
# En Unix si se trata de un archivo existeste será reemplazado.
# Renombrar un archivo o un directorio.
Path('/home/usu1/imagen2.png').replace('/home/usu1/imagen1.png')
# Si existe archivo o directorio será reemplezado
# Convertir una ruta en absoluta
print(Path('/etc/resolv.conf').resolve())
# /run/resolvconf/resolv.conf
print(Path('..').resolve()) # /home/usuario/Local
# Borrar un directorio vacío
dir1 = Path('/home/usu1/temp-1')
if dir1.exists():
dir1.rmdir()
# Conocer si hay coincidencia en dos rutas
documentos = '/home/usu1/.bashrc'
print(Path('/home/usu1/.bashrc').samefile(documentos)) # True
# Crear un enlace simbólico
Path('MiEnlace').symlink_to('imagen.png')
# Borrar un archivo o un enlace simbólico
Path('imagen.png').unlink()
Relacionado:
Ir al índice del tutorial de Python
