Мониторинг выполнения задач в 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
    


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


    У логирования в stderr есть три небольшие проблемы:
    1. Это некрасиво. Очевидно.
    2. Иногда это взрывает буфер.
    3. Иногда кто-то ещё пишет в stderr или stdout.


    Как и многие люди, которые работают с данными, я фанат 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
    


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

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



    Поддерживает итераторы:


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



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


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

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 11

      +21
        +2
        Я думаю, автор был этим вдохновлен, но если совмещать tqdm с выводом (в ipython notebook), то tqdm ломается, а эта фича нет.
          +3
          В tqdm поддержку IPython тоже добавят, думаю — см. github.com/tqdm/tqdm/pull/92. Идеи черпают из github.com/aplavin/ipy-progressbar и github.com/flying-sheep/smart-progress.
            0
            Может быть, в будущем буду пользоваться ими
              +1
              В своё время я как раз создал github.com/aplavin/ipy-progressbar для использования в notebook'ах, и сейчас действительно tqdm постепенно перенимают соответствующие фичи (а также асинхронность: __aiter__ и __anext__). Хорошо, что когда это доделают, будет один прогрессбар который можно использовать успешно в разных местах, который имеет нужные фичи и обновляется.
          +6
          Нет надобности копировать функцию в каждый notebook, можно сохранить ее в файл

          ~/.ipython/profile_default/startup/010_log_progress.py
            +1
            Полезно, спасибо!
              0
              Спасибо! Уже пользуюсь.

              Одна мелочь: для Python 3 надо последнюю строчку исправить на
              label.value = str(index or '?')
              
                0
                Кстати, еще одна мелочь: можно сделать всего один декремент так, чтобы нумерация заканчивалась именно в конце итерации цикла. А то сейчас он показывает, например, 100/100, а сотая итерация цикла только начинается и может еще долго идти.
                  0
                  Не понял. Лучше сразу пулл-реквест или патч
                    0
                    Если я правильно понял, предлагается присвоение progress.value сделать после yield record.

                Only users with full accounts can post comments. Log in, please.