Manejo de Rutas de Archivos y Directorios
Para una inmersión profunda en las operaciones prácticas del sistema de archivos, consulte nuestra publicación de blog: 10 Operaciones Esenciales del Sistema de Archivos que Todo Desarrollador Debe Conocer.
Hay dos módulos principales en Python que se ocupan de la manipulación de rutas. Uno es el módulo os.path y el otro es el módulo pathlib.
Pathlib vs Módulo OS
pathlib proporciona mucha más funcionalidad que las enumeradas anteriormente, como obtener el nombre del archivo, obtener la extensión del archivo, leer/escribir un archivo sin abrirlo manualmente, etc. Consulte la documentación oficial si tiene la intención de saber más.
Rutas de Linux y Windows
En Windows, las rutas se escriben usando barras invertidas (\) como separador entre nombres de carpetas. En sistemas operativos basados en Unix como macOS, Linux y BSDs, se utiliza la barra inclinada hacia adelante (/) como separador de ruta. Unir rutas puede ser un dolor de cabeza si su código necesita funcionar en diferentes plataformas.
Afortunadamente, el módulo pathlib de Python proporciona una forma sencilla de manejar esto.
Usando pathlib en *nix:
# pathlib.Path: manejo de rutas multiplataforma
from pathlib import Path
print(Path('usr').joinpath('bin').joinpath('spam')) # Unir componentes de ruta
usr/bin/spam
pathlib también proporciona un atajo para joinpath usando el operador /:
# Operador Path (/): forma conveniente de unir rutas (multiplataforma)
from pathlib import Path
print(Path('usr') / 'bin' / 'spam') # Usar el operador / en lugar de joinpath()
usr/bin/spam
Observe que el separador de ruta es diferente entre Windows y los sistemas operativos basados en Unix, por eso querrá usar pathlib en lugar de agregar cadenas para unir rutas.
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
Path('usr') + 'bin' + 'spam'Path('usr') / 'bin' / 'spam'Path('usr').join('bin').join('spam')Path('usr/bin/spam')Unir rutas es útil si necesita crear diferentes rutas de archivo bajo el mismo directorio.
Usando pathlib en *nix:
# Path.home(): obtener el directorio de inicio del usuario, combinar con nombres de archivo
my_files = ['accounts.txt', 'details.csv', 'invite.docx']
home = Path.home() # Obtener la ruta del directorio de inicio
for filename in my_files:
print(home / filename) # Combinar la ruta de inicio con cada nombre de archivo
/home/labex/project/accounts.txt
/home/labex/project/details.csv
/home/labex/project/invite.docx
Expandir el directorio de inicio del usuario
Usando os.path.expanduser() para expandir ~ al directorio de inicio del usuario:
import os.path
# Expandir ~ al directorio de inicio del usuario
print(os.path.expanduser('~'))
/home/labex/project
# Expandir ~/Documents a la ruta completa
print(os.path.expanduser('~/Documents'))
/home/labex/project/Documents
# Funciona con rutas que contienen ~
print(os.path.expanduser('~/myfile.txt'))
/home/labex/project/myfile.txt
El directorio de trabajo actual
Puede obtener el directorio de trabajo actual usando pathlib:
# Path.cwd(): obtener el directorio de trabajo actual
from pathlib import Path
print(Path.cwd()) # Devuelve el directorio de trabajo actual como objeto Path
/home/labex/project
Creación de nuevas carpetas
Usando pathlib en *nix:
from pathlib import Path
cwd = Path.cwd()
(cwd / 'delicious' / 'walnut' / 'waffles').mkdir()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/pathlib.py", line 1226, in mkdir
self._accessor.mkdir(self, mode)
File "/usr/lib/python3.6/pathlib.py", line 387, in wrapped
return strfunc(str(pathobj), *args)
FileNotFoundError: [Errno 2] No such file or directory: '/home/labex/project/delicious/walnut/waffles'
¡Oh no, obtuvimos un error molesto! La razón es que el directorio ‘delicious’ no existe, por lo que no podemos crear los directorios ‘walnut’ y ‘waffles’ debajo de él. Para solucionar esto, haga lo siguiente:
# mkdir(parents=True): crear directorio y todos los directorios padre si es necesario
from pathlib import Path
cwd = Path.cwd()
(cwd / 'delicious' / 'walnut' / 'waffles').mkdir(parents=True) # Crear directorios anidados
Y todo está bien :)
Rutas Absolutas vs. Relativas
Hay dos formas de especificar una ruta de archivo.
- Una ruta absoluta, que siempre comienza con la carpeta raíz
- Una ruta relativa, que es relativa al directorio de trabajo actual del programa
También están las carpetas punto (.) y doble punto (..). Estas no son carpetas reales, sino nombres especiales que se pueden usar en una ruta. Un solo punto (“punto”) para un nombre de carpeta es una abreviatura de “este directorio”. Dos puntos (“doble punto”) significa “la carpeta padre”.
Manejo de rutas absolutas
Para ver si una ruta es una ruta absoluta usando pathlib:
from pathlib import Path
Path('/').is_absolute()
True
Path('..').is_absolute()
False
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
Path('/').is_absolute()?TrueFalseNone'/'Puede extraer una ruta absoluta con pathlib:
from pathlib import Path
print(Path.cwd())
/home/labex/project
print(Path('..').resolve())
/home
Manejo de rutas relativas
Puede obtener una ruta relativa desde una ruta de inicio hasta otra ruta usando pathlib:
from pathlib import Path
print(Path('/etc/passwd').relative_to('/'))
etc/passwd
Validez de la Ruta y el Archivo
Comprobar si un archivo/directorio existe
Usando pathlib en *nix:
from pathlib import Path
Path('.').exists()
True
Path('setup.py').exists()
True
Path('/etc').exists()
True
Path('nonexistentfile').exists()
False
Comprobar si una ruta es un archivo
Usando pathlib en *nix:
from pathlib import Path
Path('setup.py').is_file()
True
Path('/home').is_file()
False
Path('nonexistentfile').is_file()
False
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
Path('setup.py').is_file() si existe setup.py?'setup.py'FalseTrueNoneComprobar si una ruta es un directorio
Usando pathlib en *nix:
from pathlib import Path
Path('/').is_dir()
True
Path('setup.py').is_dir()
False
Path('/spam').is_dir()
False
Obtener el tamaño de un archivo en bytes
Usando pathlib en *nix:
from pathlib import Path
stat = Path('/bin/python3.6').stat()
print(stat) # stat contiene otra información sobre el archivo también
os.stat_result(st_mode=33261, st_ino=141087, st_dev=2051, st_nlink=2, st_uid=0,
--snip--
st_gid=0, st_size=10024, st_atime=1517725562, st_mtime=1515119809, st_ctime=1517261276)
print(stat.st_size) # tamaño en bytes
10024
Listar directorios
Listar el contenido de un directorio usando pathlib en *nix:
from pathlib import Path
for f in Path('/usr/bin').iterdir():
print(f)
...
/usr/bin/tiff2rgba
/usr/bin/iconv
/usr/bin/ldd
/usr/bin/cache_restore
/usr/bin/udiskie
/usr/bin/unix2dos
/usr/bin/t1reencode
/usr/bin/epstopdf
/usr/bin/idle3
...
Tamaños de archivos de directorio
ADVERTENCIA
¡Los directorios también tienen un tamaño! Por lo tanto, es posible que desee verificar si una ruta es un archivo o un directorio utilizando los métodos discutidos en la sección anterior.
Usando pathlib en *nix:
from pathlib import Path
total_size = 0
for sub_path in Path('/usr/bin').iterdir():
total_size += sub_path.stat().st_size
print(total_size)
1903178911
Copiar archivos y carpetas
El módulo shutil proporciona funciones para copiar archivos, así como carpetas enteras.
import shutil
shutil.copy('/tmp/spam.txt', '/tmp/delicious')
/tmp/delicious/spam.txt
shutil.copy('/tmp/eggs.txt', '/tmp/delicious/eggs2.txt')
/tmp/delicious/eggs2.txt
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
shutil.copy()Path.copy()os.copy()shutil.copytree()Mientras que shutil.copy() copiará un solo archivo, shutil.copytree() copiará una carpeta completa y cada carpeta y archivo que contenga:
import shutil
shutil.copytree('/tmp/bacon', '/tmp/bacon_backup')
/tmp/bacon_backup
Mover y Renombrar
import shutil
shutil.move('/tmp/bacon.txt', '/tmp/eggs')
/tmp/eggs/bacon.txt
La ruta de destino también puede especificar un nombre de archivo. En el siguiente ejemplo, el archivo de origen se mueve y se renombra:
shutil.move('/tmp/bacon.txt', '/tmp/eggs/new_bacon.txt')
/tmp/eggs/new_bacon.txt
Si no existe la carpeta eggs, entonces move() renombrará bacon.txt a un archivo llamado eggs:
shutil.move('/tmp/bacon.txt', '/tmp/eggs')
/tmp/eggs
Eliminar archivos y carpetas
- Llamar a
Path.unlink()eliminará el archivo en la ruta. - Llamar a
Path.rmdir()eliminará la carpeta en la ruta. Esta carpeta debe estar vacía de cualquier archivo o carpeta. - Llamar a
shutil.rmtree(path)eliminará la carpeta en la ruta, y todos los archivos y carpetas que contenga también se eliminarán.
Inicia sesión para responder este quiz y rastrear tu progreso de aprendizaje
Path.rmdir()shutil.rmtree()Path.unlink()os.remove()Recorrer un Árbol de Directorios
El objeto Path tiene un método rglob() para iterar recursivamente sobre archivos y directorios.
from pathlib import Path
p = Path('/tmp/delicious')
for i in p.rglob('*'):
print(i)
/tmp/delicious/cats
/tmp/delicious/walnut
/tmp/delicious/spam.txt
/tmp/delicious/cats/catnames.txt
/tmp/delicious/cats/zophie.jpg
/tmp/delicious/walnut/waffles
/tmp/delicious/walnut/waffles/butter.txt