Мониторинг выполнения задач в IPython Notebook

Хотел бы поделиться простым, но полезным инструментом. Когда много работаешь с данными, часто возникают примитивные, но долгие операции, например: «скачать 10 000 урлов», «прочитать файл на 2Гб, и что-то сделать с каждой строчкой», «распарсить 10 000 html-файлов и достать заголовки». Долго смотреть в зависший терминал тревожно, поэтому долгое время я использовал следующий гениальный код:

def log_progress(sequence, every=10):
    for index, item in enumerate(sequence):
        if index % every == 0:
            print >>sys.stderr, index,
        yield item

41db19857a664e74b03d763e7243f0c3.gif

Эта функция прекрасна, больше года она кочевала у меня из задачи в задачу. Но недавно я заметил в стандартной поставке Jupyter виджет IntProgress и понял, что пора что-то менять:
fde8d9be6e4f4cae9bc1c169bfd6a688.gif
У логирования в stderr есть три небольшие проблемы:

  1. Это некрасиво. Очевидно.
  2. Иногда это взрывает буфер.
    f434c5b030974ad4b46d20c9b4790c9d.gif
  3. Иногда кто-то ещё пишет в stderr или stdout.
    31802931010d47c081560377182a6681.gif

Как и многие люди, которые работают с данными, я фанат Jupyter. Большую часть времени провожу там. Поэтому могу позволить себе следующее, несовместимое с другими средами, решение:

def log_progress(sequence, every=10):
    from ipywidgets import IntProgress
    from IPython.display import display

    progress = IntProgress(min=0, max=len(sequence), value=0)
    display(progress)
    
    for index, record in enumerate(sequence):
        if index % every == 0:
            progress.value = index
        yield record

c67996ac58024bfa9929b30e3ae56e8f.gif

Всё то же самое, только счётчик выводится не в stderr, а в специальный виджет. Очень просто и удобно. Для тех, кто тоже подсел на Jupyter, я выложил немного улучшенную версию на Гитхаб github.com/alexanderkuk/log-progress. Модуль распространяется копипейстом. Пользуйтесь на здоровье.

Улучшенная версия выводит кроме полоски ещё и счётчик. И меняет цвет в зависимости от того успешно завершилась операция или нет:
d7a1f59f61634d63a42b274ba186d1ba.gif
1bc544e8a50b419382d0fc090e087cce.gif

Поддерживает итераторы:
712255d77fd5473b8113e7bfc1bd852f.gif

Естественно, в одной ячейке может быть несколько прогресс баров:
1b448f9a5b74456091eb5b16799c7c3e.gif
95dc001dffb24852999a73ae8129a209.gif

И они даже могут работать из разных тредов:
e6469afe59ed485c84565a672d24cd50.gif

Короче, ещё раз ссылка на код github.com/alexanderkuk/log-progress.

© Habrahabr.ru