One place for hosting & domains

      Cómo usar el módulo pathlib para manipular las rutas de sistemas de archivos en Python 3


      El autor seleccionó el COVID-19 Relief Fund para que reciba una donación como parte del programa Write for DOnations.

      Introducción

      Python 3 incluye el módulo pathlib para manipular rutas de sistemas de archivos de forma agnóstica en cualquier sistema operativo. El módulo pathlib es similar al os.path, pero pathlib ofrece una interfaz de nivel más alto, y, a menudo, más conveniente, que os.path.

      Podemos identificar archivos en una computadora con rutas jerárquicas. Por ejemplo, podemos identificar el archivo wave.txt en una computadora con esta ruta: /Users/sammy/ocean/wave.txt. Cada sistema operativo tiene una manera ligeramente distinta de representar rutas. Windows puede representar la ruta al archivo wave.txt de la siguiente manera: C:Userssammyoceanwave.txt.

      El módulo pathlib le puede resultar útil si desea a crear o mover archivos en el sistema de archivos de su programa de Python, enumerar los archivos del sistema de archivos que coincidan con una extensión o un patrón determinado o crear rutas de archivos apropiadas para el sistema operativo basadas en colecciones de cadenas sin procesar. Si bien es posible usar otras herramientas (como el módulo os.path) para realizar muchas de estas tareas, el módulo pathlib le permite realizar estas operaciones con un alto grado de legibilidad y una cantidad de código mínima.

      En este tutorial, revisaremos algunas de las maneras de usar el módulo pathlib para representar y manipular las rutas de los sistemas de archivos.

      Requisitos previos

      Para sacar el máximo provecho de este tutorial, se recomienda tener cierta familiaridad con la programación en Python 3. Puede consultar estos tutoriales para obtener la información de fondo necesaria:

      Cómo crear instancias Path

      El módulo pathlib proporciona varias clases, pero una de las más importantes es la clase Path. Las instancias de la clase Path representan una ruta a un archivo o un directorio en el sistema de archivos de nuestra computadora.

      Por ejemplo, el siguiente código inicia una instancia Path que representa una parte de la ruta a un archivo wave.txt:

      from pathlib import Path
      
      wave = Path("ocean", "wave.txt")
      print(wave)
      

      Si ejecutamos este código, obtendremos un resultado como el siguiente:

      Output

      ocean/wave.txt

      from pathlib import Path permite que la clase Path esté disponible en nuestro programa. Luego, Path("ocean", "wave.txt") crea una instancia de Path nueva. El resultado muestra que Python ha añadido el separador / adecuado del sistema operativo entre los dos componentes de la ruta que le proporcionamos: "ocean" y "wave.txt".

      Nota: Sus resultados pueden diferir ligeramente de los que se muestran como ejemplo en este tutorial en función del sistema operativo que utilice. Si utiliza Windows, por ejemplo, su resultado para este primer ejemplo puede tener este aspecto: oceanwave.txt.

      Actualmente, el objeto Path asignado a la variable wave contiene una ruta relativa. En otras palabras, ocean/wave.txt puede existir en varias ubicaciones de nuestro sistema de archivos. Por ejemplo, puede estar presente en /Users/user_1/ocean/wave.txt o /Users/user_2/research/ocean/wave.txt, pero no especificamos exactamente a cuál nos estamos refiriendo. Por el contrario, una ruta absoluta se refiere inequívocamente a una ubicación en el sistema de archivos.

      Puede usar Path.home() para obtener la ruta absoluta al directorio principal del usuario actual:

      home = Path.home()
      wave_absolute = Path(home, "ocean", "wave.txt")
      print(home)
      print(wave_absolute)
      

      Si ejecutamos este código, obtendremos un resultado similar al siguiente:

      Output

      /Users/sammy /Users/sammy/ocean/wave.txt

      Nota: Como se mencionó anteriormente, su resultado variará dependiendo de su sistema operativo. Por supuesto, su directorio principal también será distinto de /Users/sammy.

      Path.home() devuelve una instancia Path con una ruta absoluta al directorio principal del usuario actual. Luego, pasamos esta instancia de Path y las cadenas "ocean" y "wave.txt" a otro constructor de Path para crear una ruta absoluta al archivo wave.txt. El resultado indica que la primera línea es el directorio principal y la segunda, el directorio principal más ocean/wave.txt.

      Este ejemplo también ilustra una característica importante de la clase Path: el constructor Path acepta tanto cadenas como objetos preexistentes de Path.

      Analicemos con mayor detalle cómo es que el constructor Path admite tanto cadenas como de objetos de Path:

      shark = Path(Path.home(), "ocean", "animals", Path("fish", "shark.txt"))
      print(shark)
      

      Si ejecutamos este código de Python, obtendremos un resultado similar al siguiente:

      Output

      /Users/sammy/ocean/animals/fish/shark.txt

      shark es un Path a un archivo que construimos usando tanto objetos Path (Path.home() y Path("fish", "shark.txt")) como cadenas ("ocean" y "animals"). El constructor Path gestiona de forma inteligente ambos tipos de objetos y los une de forma correcta usando el separador correspondiente del sistema operativo, en este caso: /.

      Acceder a los atributos de los archivos

      Ahora que hemos aprendido a crear instancias de Path, vamos a repasar cómo puede usar esas instancias para acceder a información sobre un archivo.

      Podemos usar los atributos name y suffix para acceder a los nombres y los sufijos de archivos:

      wave = Path("ocean", "wave.txt")
      print(wave)
      print(wave.name)
      print(wave.suffix)
      

      Al ejecutar este código, obtendremos un resultado similar al siguiente:

      Output

      /Users/sammy/ocean/wave.txt wave.txt .txt

      Este resultado indica que el nombre del archivo al final de nuestra ruta es wave.txt y el sufijo de ese archivo es .txt.

      Las instancias de Path también ofrecen la función with_name, que le permite crear de forma sencilla un objeto Path nuevo con un nombre distinto:

      wave = Path("ocean", "wave.txt")
      tides = wave.with_name("tides.txt")
      print(wave)
      print(tides)
      

      Si ejecutamos este código, obtendremos un resultado similar al siguiente:

      ocean/wave.txt
      ocean/tides.txt
      

      El código, primero, construye una instancia Path que apunta a un archivo llamado wave.txt. Luego, invoca el método with_name en wave para devolver una segunda instancia Path que apunta a un archivo nuevo denominado tides.txt. La parte del directorio ocean/ de la ruta permanece intacta, por lo tanto, la ruta final queda establecida como ocean/tides.txt

      Acceder a antecesores

      A veces, resulta útil acceder a directorios que contienen una ruta determinada. Consideremos un ejemplo:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      print(shark)
      print(shark.parent)
      

      Si ejecutamos este código, obtendremos un resultado similar al siguiente:

      Output

      ocean/animals/fish/shark.txt ocean/animals/fish

      El atributo parent en una instancia de Path devuelve el antecesor más inmediato de una ruta de archivos determinada. En este caso, devuelve el directorio que contiene el archivo shark.txt: ocean/animals/fish.

      Podemos acceder al atributo parent varias veces seguidas para recorrer el árbol de ancestros de un archivo determinado:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      print(shark)
      print(shark.parent.parent)
      

      Si ejecutamos este código, obtendremos el siguiente resultado:

      Output

      ocean/animals/fish/shark.txt ocean/animals

      El resultado es similar al anterior, pero, ahora, hemos llegado a un nivel más alto al acceder a .parent por segunda vez. El directorio ocean/animals se encuentra dos directorios por encima de shark.txt.

      Usar Glob para enumerar archivos

      También es posible usar la clase Path para enumerar archivos usando el método glob.

      Imaginemos que tenemos una estructura de directorios similar a la siguiente:

      └── ocean
          ├── animals
          │   └── fish
          │       └── shark.txt
          ├── tides.txt
          └── wave.txt
      

      Un directorio ocean que contiene los archivos tides.txt y wave.txt. Tenemos un archivo denominado shark.txt anidado en el directorio ocean, un directorio animals y otro fish: ocean/animals/fish.

      Para enumerar todos los archivos .txt del directorio ocean, podríamos escribir lo siguiente:

      for txt_path in Path("ocean").glob("*.txt"):
          print(txt_path)
      

      Este código tendría un resultado similar al siguiente:

      Output

      ocean/wave.txt ocean/tides.txt

      El patrón glob __"*.txt" busca todos los archivos que terminan en .txt. Como el código del ejemplo ejecuta ese glob en el directorio ocean, devuelve los dos archivos .txt del directorio ocean: wave.txt y tides.txt.

      Nota: Para duplicar los resultados que se muestran en este ejemplo, copie la estructura de directorios que se ilustra aquí en su computadora.

      También podemos usar el método glob de manera recursiva. Para enumerar todos los archivos .txt del directorio ocean y todos sus subdirectorios, podemos escribir lo siguiente:

      for txt_path in Path("ocean").glob("**/*.txt"):
          print(txt_path)
      

      Al ejecutar este código, obtendríamos un resultado similar al siguiente:

      Output

      ocean/wave.txt ocean/tides.txt ocean/animals/fish/shark.txt

      La sección ** del patrón glob coincidirá con este directorio y todos sus subdirectorios de manera recursiva. Por tanto, no solo tenemos los archivos wave.txt y tides.txt en el resultado, sino que también recibimos el archivo shark.txt que estaba anidado en ocean/animals/fish.

      Calcular rutas relativas

      Podemos usar el método Path.relative_to para calcular rutas relacionadas entre sí. El método relative_to es útil cuando, por ejemplo, se desea recuperar una porción de una ruta de archivos larga.

      Analice el siguiente código:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      below_ocean = shark.relative_to(Path("ocean"))
      below_animals = shark.relative_to(Path("ocean", "animals"))
      print(shark)
      print(below_ocean)
      print(below_animals)
      

      Si ejecutamos este código, obtendremos un resultado similar al siguiente:

      Output

      ocean/animals/fish/shark.txt animals/fish/shark.txt fish/shark.txt

      El método relative_to devuelve un nuevo objeto Path relacionado con el argumento determinado. En nuestro ejemplo, calculamos el Path a shark.txt en relación con el directorio ocean y, luego, en relación con los directorios ocean y animals.

      Si relative_to no puede calcular una respuesta porque le indicamos una ruta no relacionada, presenta un ValueError:

      shark = Path("ocean", "animals", "fish", "shark.txt")
      shark.relative_to(Path("unrelated", "path"))
      

      Obtendremos una excepción ValueError generada a partir de este código que será similar a la siguiente:

      Output

      Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/Python3.8/pathlib.py", line 899, in relative_to raise ValueError("{!r} does not start with {!r}" ValueError: 'ocean/animals/fish/shark.txt' does not start with 'unrelated/path'

      unrelated/path no forma parte de ocean/animals/fish/shark.txt, por lo tanto, Python no puede calcular una ruta relativa.

      Conclusión

      El módulo pathlib es un componente importante de la biblioteca estándar de Python que nos permite manipular rutas de sistemas de archivos de forma rápida en cualquier sistema operativo. En este tutorial, ha aprendido a usar algunas de las herramientas clave de pathlib para acceder a los atributos de archivos, enumerar archivos con patrones glob y desplazarse por archivos y directorios principales.

      El módulo pathlib expone clases y utilidades adicionales que no abarcamos en este tutorial. Ahora que tiene una referencia, puede usar la documentación del módulo pathlib para obtener más información sobre otras clases y utilidades disponibles.

      Si está interesado en utilizar otras bibliotecas de Python, consulte los siguientes tutoriales:



      Source link