Время прочтения: 4 мин.
Начав поиск в интернете, мне попались два варианта, это модули os и Pathlib.
Первый попавшийся модуль был os. Данный модуль является очень популярным и давно используется для работы с папками и файлами ОС.
(Тестовые данные для проверки скриптов содержат три Excel-файла, каждый примерно по 45 тыс. строк.)
Реализация скрипта на модуле os.
import pandas as pd
import os
test_list = [ ]
for root, dirs, files in os.walk ('U:\\Desktop\\test\\'):
test_list.extend ([os.path.join (root, file) for file in files
if file.endswith ('xlsx')])
result = pd.DataFrame()
for file in test_list:
f = pd.ExcelFile(file)
for sheet in f.sheet_names:
df = pd.read_excel((file), sheet_name=sheet)
result=result.append(df)
result.to_excel('U:/Desktop/test/all_files.xlsx', index=None)
Wall time:1min 13s
Но на большом количестве файлов, около 600, скрипт работал крайне долго и было решено поискать какое-то другое решение данной задачи, с тем учетом, чтобы его можно было использовать и в будущем.
При повторном поиске был найден модуль Pathlib, о котором помимо весьма положительных отзывов, также отмечается удобство в работе, хоть он пока и не такой популярный как модуль os.
Не заставив себя долго ждать, я запустил скрипт с использованием модуля Pathlib:
from pathlib import Path
import pandas as pd
path = Path (“U:/Desktop/test”)
df = pd.concat ([pd.read_excel(f)
for f in path.glob(“*.xlsx”)],
ignore_index=True)
df.to_excel('U:/Desktop/test/all_files.xlsx'
, index=None)
Wall time: 56.6 s
Как видно на тестовых данных, разница во времени почти 30%. На рабочих данных разница была тоже очень заметна. Следовательно, результат работы был получен намного быстрее. Если сравнить визуально скрипты, то можно увидеть, что скрипт на Pathlib выглядит намного «легче».
Также стоит отметить, что при работе с os используется разделитель «\\» между директориями, в то время как в Pathlib используется «/»
Pathlib.
Вот как описывается в документации модуль.
«Если вы никогда раньше не использовали этот модуль или просто не уверены, какой класс подходит для вашей задачи, Path скорее всего это то, что вам нужно. Он создаст конкретный путь для платформы, на которой выполняется код.»
По описанию Pathlib работа с ним должна быть простой, особенно, если вы впервые сталкиваетесь с данным модулем.
Небольшое сопоставление различных os методов с их соответствующими эквивалентами Path:
os и os.path | Pathlib | Описание метода |
os.path.abspath() | Path.absolute() | Получить абсолютный путь, без нормализации и символических ссылок |
os.path.realpath() | Path.resolve() | Получить абсолютный путь, включая любые символические ссылки. |
os.mkdir | Path.mkdir() | Создать новую директорию |
os.replace() | Path.replace() | Переименовать директорию |
os.remove(), os.unlink() | Path.unlink() | Удалить файл или символическую ссылку |
os.getcwd() | Path.cwd() | Возвращает текущий каталог |
os.listdir() | Path.iterdir() | Возвращает объект, если путь указывает на каталог |
os.stat() | Path.stat(), Path.owner(), Path.group() | Получить статус файла |
os.symlink() | Path.symlink_to() | Создает символическую ссылку |
os.link() | Path.hardlink_to() | Создает жесткую ссылку |
os.path.basename() | PurePath.name | Получить конечный компонент пути |
os.path.join() | PurePath.joinpath() | Объединение путей |
os.path.splitext() | PurePath.stem, PruePath.suffix | Конечный компонент без его суффикса (расширения) |
Как видно, Pathlib содержит тот же набор методов, что и os, следовательно, в функциональном плане мы ничего не теряем, при работе с Pathlib вместо os.
Рассмотрю ряд основных методов Pathlib:
Получить текущий каталог. Это можно сделать используя Path.cwd():
from pathlib import Path
Path.cwd()
WindowsPath ('C:/Users/17780049')
Создать новую директорию. Path.mkdir():
from pathlib import Path
test_folder = Path (‘test_folder’)
print(test_folder.exists())
test_folder.mkdir(exist_ok=True)
print(test_folder.exists())
False
True
Почти также можно создать и новый файл используя Path.touch():
from pathlib import Path
test_file = Path (‘test_folder/test_file.txt’)
print(test_file.exists())
test_file.touch(exist_ok=True)
print(test_file.exists())
False
True
Pathlib поддерживает свойство parent и различные связанные с этим свойством методы.
Можно создать несколько папок используя всё тот же метод Path.mkdir(), только нужно указать parents=True, в этом случае будут созданы папки, которых нет в пути. А используя Path.parent мы можем перемещаться по каталогам:
from pathlib import Path
test_folder = Path (‘test_folder/ test_folder_1/ test_folder_2/ test_folder_3/’)
test_folder.mkdir (parents=True, exist_ok=True)
print(test_ folder.parent)
print(test_ folder.parent. parent)
print(test_ folder.parent. parent. parent)
test_folder\ test_folder_1\ test_folder_2
test_folder\ test_folder_1
test_folder
Но чтобы избежать многочисленный вызов метода parent можно воспользоваться Path.parents:
list(test_folder.parents)
[WindowsPath(‘test_folder/ test_folder_1/ test_folder_2’),
WindowsPath(‘test_folder/ test_folder_1’)
WindowsPath(‘test_folder’)
WindowsPath(‘.’)]
Здесь же можно использовать индексы для выбора необходимой папки:
print(list(test_folder.parents)[0])
print(list(test_folder.parents)[2])
test_folder\ test_folder_1\ test_folder_2
test_folder
Подводя небольшой итог использования модуля Pathlib:
- достаточно прост в использовании и понимании его работы,
- имеет много возможностей для работы с файлами,
- код смотрится лаконичнее,
- работает быстрее модуля os.
Более подробно можно ознакомится с документацией на официальном сайте
А каким модулем пользуетесь вы?