- Пишем прогресс-бары при помощи tqdm
- tqdm и функции
- tqdm.notebook в списке
- Несколько индикаторов выполнения
- tqdm для Data Science
- Загружаем датасет
- Применение функции с помощью tqdm
- Утилита для параллельной обработки
- Отслеживаем прогресс выполнения в Python
- Используем Progress
- Используем tqdm
- Используем alive-progress
- GUI индикатор прогресса для скрипта
- Индикатор в приложении PySimpleGUI
- Заключение
Пишем прогресс-бары при помощи tqdm
В переводе с арабского tqdm (taqadum) означает прогресс; библиотека с таким названием используется как раз для создания индикаторов прогресса. Просто оберните любой итерируемый объект в функцию – tqdm(iterable) – и готово.
Таким образом можно создать прогресс-бары для обработки данных, моделей машинного обучения или загрузки данных из интернета. Но сначала нужно установить библиотеку:
А теперь без лишних разговоров берите копируйте код ниже, запускайте у себя и любуйтесь. Библиотека tqdm помимо, собственно, самого прогресс-бара, показывает также количество итераций, время, затраченное на выполнение цикла, и частоту итераций в секунду. Видели ли вы что-то прекраснее сегодня?
from tqdm import tqdm for i in tqdm(range(10000)): pass
Ладно, давайте теперь научимся настраивать наши индикаторы и использовать при обработке датафреймов. Заодно узнаем о некоторых дополнительных фичах библиотеки.
tqdm и функции
В примере ниже мы создали функцию fun , которая принимает целое число x и исполняется с задержкой в x секунд. Потом мы обернули tqdm вокруг функции range , которая будет запускать цикл на 10 итераций. Для выполнения первой итерации потребуется 0 секунд. Вторая итерация займет 1 секунду, и так далее. Для завершения цикла потребовалось 45 секунд, и мы при этом видим анимированный индикатор выполнения.
from tqdm import trange, tqdm from time import sleep # функция с задержкой исполнения def fun(x): sleep(x) return x # цикл с прогресс-баром for i in tqdm(range(10)): fun(i)
tqdm.notebook в списке
А здесь будем использовать модуль tqdm.notebook для отображения прогресс-баров в Jupyter Notebook с помощью виджетов Ipython.
Сначала создаём простой список различных цветов. Затем с помощью цикла выведем их названия одно за другим с задержкой в одну секунду. Заворачиваем список в модуль, и радуемся анимированному индикатору.
from tqdm.notebook import tqdm colors = ["Blue", "Green", "Yellow", "White", "Gray", "Black"] for x in tqdm(colors): sleep(1) print(x)
Несколько индикаторов выполнения
С помощью вложенных циклов напишем несколько прогресс-баров, имитирующих визуализацию хода обучения модели машинного обучения.
- trange – это комбинация из функции tqdm , обёрнутой вокруг функции range .
- Внешний цикл будет выполняться за 10 итераций с задержкой 0,01 сек.
- desc используется для обозначения индикатора выполнения.
- Внутренний цикл будет выполняться за 10 000 итераций с задержкой 0,001 сек.
Посмотрите, насколько круто выглядит анимация! Скопируйте код ниже, подшаманьте над ним немного на своё усмотрение и запустите.
from tqdm.notebook import trange for i in trange(10, desc="Traning Model on 10 Epochs"): sleep(0.01) for x in trange(10000, desc=f"Epoch "): sleep(0.001)
tqdm для Data Science
В этой части мы соединим функционал библиотек tqdm и pandas и с помощью progress_apply применим функцию к датафрейму, чтобы добавить прогресс-бар.
Загружаем датасет
Сначала загрузим набор данных по бронированию отелей с Kaggle. Затем отобразим пять верхних строк датафрейма.
Набор содержит 119390 строк с данными о бронирований номеров в городских гостиницах и курортных отелях в период с 1 июля 2015 года по 31 августа 2017 года, включая фактически прибывшие и отмененные бронирования.
import pandas as pd df = pd.read_csv("hotel_booking.csv") df.head().to_frame()
Применение функции с помощью tqdm
Создадим новый столбец user_name с именами клиентов.
- функция tqdm.pandas нужна для инициализации прогресс-бара в датафрейме. Добавим к нему название Processing the name colum.
- Функция user_name приводит строку к нижнему регистру и заменяет пробелы на » — «.
- Применим функцию к датафрейму с помощью .progress_apply() . Она аналогична функции apply() . А для функции map() можно использовать .progress_map() .
- Отображаем три верхние строки нашего набора данных
# задаём имя прогресс-бару tqdm.pandas(desc="Processing the name column") # преобразование текста def user_name(text): return text.lower().replace(" ","-") # применение функции к столбцу df["user_name"] = df["name"].progress_apply(user_name) # вывод первых трёх строк df.head(3)
Утилита для параллельной обработки
Библиотека tqdm нужна не только для написания прогресс-баров для циклов, в ней есть также утилиты для параллельной обработки, например, функция tqdm.contrib.concurrent .
Давайте попробуем извлечь доменные имена из адресов электронной почты в столбце email .
- Импортируем process_map из tqdm.contrib.concurrent .
- С помощью функции provider_extraction разделим текст сначала по знаку » @ «, затем по знаку » . «.
- Применяем функцию process_map к столбцу email . В качестве параметров укажем max_worker , равный 8, основываясь на количестве ядер процессора, и зададим chunksize , равный 64.
- Добавим имя прогресс-бара и настроим его цвет — пусть будет зелёный.
- Выводим первые пять строк столбца email_provider .
from tqdm.contrib.concurrent import process_map # функция для извлечения email def provider_extraction(email): return email.split("@")[1].split(".")[0] # применения функции к столбцу df["email_provider"] = process_map( provider_extraction, df["email"], max_workers=8, chunksize=64, desc="Extracting Email provider", colour='green' ) df["email_provider"].head().to_frame()
Мы поэкспериментировали с библиотекой tqdm, но она, на самом деле, может гораздо больше. Почитайте документацию и узнаете о других её возможностях.
Отслеживаем прогресс выполнения в Python
Индикаторы прогресса (progress bar) — визуальное отображение процесса работы. Они избавляют нас от необходимости беспокоиться о том, не завис ли скрипт, дают интуитивное представление о скорости его выполнения и подсказывают, сколько времени осталось до завершения.
Человек ранее не использовавший индикаторы прогресса может предположить, что их внедрение может сильно усложнить код. К счастью, это не так. Небольшие примеры ниже покажут, как быстро и просто начать отслеживать прогресс в консоли или в интерфейсе быстро набирающей популярность графической библиотеки PySimpleGUI.
Используем Progress
Всё, что от вас потребуется, это указать количество ожидаемых итераций, тип индикатора и вызывать функцию при каждой итерации:
import time from progress.bar import IncrementalBar mylist = [1,2,3,4,5,6,7,8] bar = IncrementalBar('Countdown', max = len(mylist)) for item in mylist: bar.next() time.sleep(1) bar.finish()
Есть индикаторы на любой вкус:
Используем tqdm
Следующей на очереди идёт библиотека tqdm.
Быстрый и расширяемый индикатор прогресса для Python и CLI
Всего один вызов функции понадобится для получения результата аналогичного предыдущему:
import time from tqdm import tqdm mylist = [1,2,3,4,5,6,7,8] for i in tqdm(mylist): time.sleep(1)
Само собой, в комплекте идёт куча настроек и опций.
Используем alive-progress
Ещё один вариант синтаксиса, побольше дефолтных анимаций, чем в предыдущих примерах:
from alive_progress import alive_bar import time mylist = [1,2,3,4,5,6,7,8] with alive_bar(len(mylist)) as bar: for i in mylist: bar() time.sleep(1)
GUI индикатор прогресса для скрипта
Иногда возникает необходимость предоставить конечному пользователю графический индикатор.
Сколько кода нужно, чтобы достигнуть такого результата? Немного:
import PySimpleGUI as sg import time mylist = [1,2,3,4,5,6,7,8] for i, item in enumerate(mylist): sg.one_line_progress_meter('This is my progress meter!', i+1, len(mylist), '-key-') time.sleep(1)
Индикатор в приложении PySimpleGUI
Рассмотрим реализацию индикатора в PySimpleGUI.
import PySimpleGUI as sg import time mylist = [1,2,3,4,5,6,7,8] progressbar = [ [sg.ProgressBar(len(mylist), orientation='h', size=(51, 10), key='progressbar')] ] outputwin = [ [sg.Output(size=(78,20))] ] layout = [ [sg.Frame('Progress',layout= progressbar)], [sg.Frame('Output', layout = outputwin)], [sg.Submit('Start'),sg.Cancel()] ] window = sg.Window('Custom Progress Meter', layout) progress_bar = window['progressbar'] while True: event, values = window.read(timeout=10) if event == 'Cancel' or event is None: break elif event == 'Start': for i,item in enumerate(mylist): print(item) time.sleep(1) progress_bar.UpdateBar(i + 1) window.close()
Заключение
Как видите, нет ничего сложного в добавлении информации о прогрессе выполнения: кода немного, а отзывчивость повышается очень сильно. Используйте индикаторы, чтобы больше никогда не гадать, завис ли процесс или нет!