One place for hosting & domains

      Использование модуля pathlib для манипуляции путями файловых систем в Python 3


      Автор выбрал COVID-19 Relief Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

      Python 3 включает модуль pathlib для манипуляции путями файловых систем независимо от операционной системы. pathlib похож на модуль os.path, но pathlib предлагает более развитый и удобный интерфейс по сравнению с os.path.

      Мы можем идентифицировать файлы на компьютере с помощью иерархических путей. Например, мы можем идентифицировать файл wave.txt на компьютере с помощью этого пути: /Users/sammy/ocean/wave.txt. Операционные системы представляют пути несколько по-разному. Windows может представлять путь к файлу wave.txt как C:Userssammyoceanwave.txt.

      Модуль pathlib может быть полезен, если в программе Python вы создаете или перемещаете файлы в файловой системе, указывая все файлы в файловой системе, совпадающие с данным расширением или шаблоном, или создаете пути файла, соответствующие файловой системе на основе наборов неформатированных строк. Хотя вы можете использовать другие инструменты, например модуль os.path, для выполнения большей части этих задач, модуль pathlib позволяет выполнять эти операции с большей степенью читаемости и минимальным количеством кодов.

      В этом обучающем модуле мы рассмотрим некоторые способы использования модуля pathlib для представления и манипуляции путями файловых систем.

      Предварительные требования

      Чтобы получить максимум знаний из этого обучающего модуля, рекомендуется иметь небольшое представление о программировании на Python 3. Дополнительную информацию можно найти в следующих обучающих руководствах:

      Построение экземпляров Path

      Модуль pathlib предоставляет несколько классов, но одним из наиболее важных является класс Path. Экземпляры класса Path представляют путь к файлу или каталогу в файловой системе вашего компьютера.

      Например, следующий код инстанциирует экземпляр Path, который представляет часть пути к файлу wave.txt:

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

      Если запустить этот код, результат будет выглядеть следующим образом:

      Output

      ocean/wave.txt

      from pathlib import Path делает класс Path доступным для нашей программы. Затем Path("ocean", "wave.txt") инстанциирует новый экземпляр Path. Вывод отображает, что Python добавил соответствующий разделитель оперативной системы / между двумя заданными нами компонентами пути "ocean" и "wave.txt".

      Примечание. В зависимости от операционной системы вывод может немного отличаться от примеров, приведенных в данном руководстве. Если вы работаете в Windows, например, ваш вывод для этого первого примера может выглядеть как oceanwave.txt.

      В настоящее время объект Path, назначенный на переменную wave, содержит относительный путь. Другими словами, ocean/wave.txt может существовать в нескольких местах в нашей файловой системе. В качестве примера он может существовать в /Users/user_1/ocean/wave.txt или /Users/user_2/research/ocean/wave.txt, но мы не указали к какому из них конкретно мы обращаемся. Абсолютный путь, напротив, однозначно четко указывает на расположение в файловой системе.

      Вы можете использовать Path.home() для получения абсолютного пути к домашнему каталогу текущего пользователя:

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

      Если запустить этот код, результат будет выглядеть приблизительно следующим образом:

      Output

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

      Примечание. Как упоминалось ранее, вывод будет зависеть от операционной системы. Ваш домашний каталог также будет отличаться от /Users/sammy.

      Path.home() возвращает экземпляр Path с абсолютным путем в домашний каталог текущего пользователя. Затем мы передадим этот экземпляр Path и строки "ocean" и "wave.txt" в другой конструктор Path, чтобы создать абсолютный путь к файлу wave.txt. Вывод показывает, что первая строка — это домашний каталог, а вторая строка — домашний каталог плюс ocean/wave.txt.

      Этот пример также иллюстрирует важную функцию класса Path: конструктор Path принимает обе строки и ранее существовавшие объекты Path.

      Давайте более детально рассмотрим поддержку строк и объектов Path в конструкторе Path:

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

      Если запустить этот код Python, результат будет выглядеть следующим образом:

      Output

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

      shark — это Path к файлу, который мы создали с помощью объектов Path (Path.home() и Path("fish", "shark.txt") и строк "ocean" и "animals"). Конструктор Path интеллектуально обрабатывает оба типа объектов и аккуратно соединяет их с помощью соответствующего разделителя операционной системы, в данном случае /.

      Доступ к атрибутам файла

      Теперь, когда мы узнали, как создать экземпляры Path, давайте рассмотрим, как можно использовать эти экземпляры для доступа к информации о файле.

      Мы можем использовать атрибуты name и suffix для доступа к именам и расширениям файлов:

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

      Запустив этот код, мы получим вывод, аналогичный следующему:

      Output

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

      Этот вывод показывает, что имя файла в конце нашего пути — wave.txt, а расширение файла — .txt.

      Экземпляры Path также предлагают функцию with_name, позволяющую беспрепятственно создавать новый объект Path с другим именем:

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

      Если запустить его, результат будет выглядеть следующим образом:

      ocean/wave.txt
      ocean/tides.txt
      

      Код сначала создает экземпляр Path, указывающий на файл с именем wave.txt. Затем мы вызовем метод with_name в wave, чтобы вернуть второй экземпляр Path, указывающий на новый файл с именем tides.txt. Часть каталога ocean/ остается неизмененной и оставляет финальный путь в виде ocean/tides.txt

      Доступ к предшествующим объектам

      Иногда полезно получить доступ к каталогам, содержащим определенный путь. Давайте рассмотрим пример:

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

      Если запустить этот код, результат будет выглядеть следующим образом:

      Output

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

      Атрибут parent в экземпляре Path возвращает ближайшего предшественника пути данного файла. В этом случае он возвращает каталог с файлом shark.txt: ocean/animals/fish.

      Мы можем получать доступ к атрибуту parent несколько раз в строке, чтобы пройти вверх по корневому дереву данного файла:

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

      Если мы выполним этот код, мы увидим следующие результаты:

      Output

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

      Вывод будет похож на предыдущий вывод, но теперь мы перешли на уровень выше, получив доступ к .parent во второй раз. Два каталога от shark.txt — это каталог ocean/animals.

      Использование шаблона поиска для списка файлов

      Также можно использовать класс Path для списка файлов с помощью метода glob.

      Допустим, у нас есть структура каталога, которая выглядит следующим образом:

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

      Каталог ocean содержит файлы tides.txt и wave.txt. У нас есть файл с именем shark.txt, вложенный в каталог ocean, каталог animals и каталог fish: ocean/animals/fish.

      Чтобы перечислить все файлы .txt в каталоге ocean, можно сказать:

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

      Этот код произведет следующий вывод:

      Output

      ocean/wave.txt ocean/tides.txt

      Шаблон поиска "*.txt" находит все файлы, заканчивающиеся на .txt. Поскольку пример кода выполняет этот поиск в каталоге ocean, он возвращает два файла .txt в каталоге ocean: wave.txt и tides.txt.

      Примечание. Если вы хотите дублировать выводы, указанные в данном примере, вам потребуется имитировать структуру каталога, изображенную здесь, на компьютере.

      Также мы можем использовать метод glob рекурсивно. Чтобы перечислить все файлы .txt в каталоге ocean и все его подкаталоги, мы можем сказать:

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

      Если запустить этот код, результат будет выглядеть следующим образом:

      Output

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

      Часть ** шаблона поиска будет соответствовать этому каталогу и всем каталогам под ним рекурсивно. Поэтому в выводе у нас будут не только файлы wave.txt и tides.txt, но также мы получим файл shark.txt, вложенный в ocean/animals/fish.

      Вычисление относительных путей

      Мы можем использовать метод Path.relative_to для вычисления путей, относящихся друг к другу. Метод relative_to полезен, если, например, вы хотите получить часть длинного пути файла.

      Рассмотрите следующий код:

      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)
      

      Если запустить его, результат будет выглядеть следующим образом:

      Output

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

      Метод relative_to возвращает новый объект Path, относящийся к данному аргументу. В нашем примере мы вычислим Path к shark.txt, относящийся к каталогу ocean, а затем относящийся к обоим каталогам ocean и animals.

      Если relative_to не сможет вычислить ответ, поскольку мы даем ему не связанный путь, он выдаст ValueError:

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

      Мы получим исключение ValueError, возникшее из этого кода, которое будет выглядеть следующим образом:

      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 не является частью ocean/animals/fish/shark.txt, поэтому Python не сможет вычислить относительный путь.

      Заключение

      Модуль pathlib — это мощная часть стандартной библиотеки Python, которая позволяет нам быстро манипулировать путями файловых систем в любой операционной системе. В этом обучающем модуле мы научились использовать некоторые ключевые утилиты pathlib для доступа к атрибутам файла, спискам файлов с помощью шаблонов поиска и переходить к родительским файлам и каталогам.

      Модуль pathlib представляет дополнительные классы и утилиты, которые мы не охватили в данном руководстве. После получения базового уровня вы можете использовать документацию модуля pathlib для получения дополнительной информации о других имеющихся классов и утилитах.

      Если вас интересуют другие библиотеки Python, ознакомьтесь со следующими обучающими модулями:



      Source link


      Leave a Comment