Мелкая питонячая радость #9: консольные приложения с человеческим лицом

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


    В мире есть много прекрасных разработчиков, которые могут выдавать эффектные алгоритмы, изящные архитектуры и прекрасный код. Но эти же программеры берут и пишут весьма посредственно организованный код какого-нибудь маленького консольного скрипта для расчета аналитики или патча данных в базе. Никакой разбивки на классы и функции, корявая передача аргументов, примитивный вывод малопонятной информации с помощью print()


    Сегодня мы поговорим о том, как сделать лучше программы, на которые большинству плевать — одноразовые консольные утилитки и скрипты.


    image


    python-nubia


    Библиотека от второй по значимости в мире корпорации добра — Facebook. Тамошних инженеров тоже порядком утомил хаос в консольных приложениях, поэтому они решили снабдить их интерактивным интерфейсом. Конечно же, текстовым.


    image


    • Автокомплит для функций, доступных в вашем консольном скрипте.
    • Можно подключать автокомплит на уровне терминала (работает в bash и zsh).
    • Приятный и красивый статус бар, который покажет пользователю, что же происходит.
    • Подсказки и валидации по наборам аргументов функций и их типам.

    Termgraph


    С выводом информации в консоль у многих вообще беда. Как говорилось выше, дело часто сводится к простому выводу print(). Читать такое, конечно, не очень удобно.


    Для того, чтобы сделать отрисовку того, что происходит в программе, есть либа Termgraph


    Она позволяет делать такие вот картинки в терминале



    Или такие, посложнее



    Используя простой бар, можно показывать прогресс выполнения программы в виде красивой полоски — и это уже будет круто и куда приятней вывода непонятных значений принтом.


    Fabric


    Скрипты для выполнения на удаленных машинах — отдельная боль. Конечно, мы живем в веке DevOps, когда кучи задач решаются с помощью Salt и Ansible. Но бывает и такое, что нужно регулярно логиниться на кластер удаленных тачек и выполнять там пачки команд. Для этого и есть fabric


    • Поддержка разных списков хостов — можно выполнять команды на серверах БД, в кластере приложения — просто пропишите удаленные тачки в скрипт.
    • Разные политики авторизции для тачек — можно юзать и ключи, и пароли.
    • Разбивка скрипта на подкоманды, группировка подкоманд в команды побольше — можно делать сколь угодно сложную логическую структуру кода, который вы хотите запускать.
    • И, конечно же, можно мешать в коде команды терминала и питонячий код!

    Fabric построен вокруг Paramiko и вообще вы можете выполнять команды с помощью этой низкоуровневой библиотеки общения по SSH. Но Fabric дает необходимый уровень абстракции, который позволяет делать понятным и легкоиспользуемым.


    python-prompt-toolkit


    Эта либа превращает простой скрипт в реально мощное консольное приложение.


    Например, можно добавить строку запроса команд в текстовый интерфейс.


    from prompt_toolkit import prompt
    
    while 1:
        user_input = prompt('>')
        print(user_input)

    А после этого можно добавить историю использованных команд, прямо как в вашем терминале.


    
    from prompt_toolkit import prompt
    from prompt_toolkit.history import FileHistory
    
    while 1:
        user_input = prompt('>', 
                            history=FileHistory('history.txt'),
                           )
        print(user_input)

    А можно сделать автоподсказки строк из истории ввода.


    
    from prompt_toolkit import prompt
    from prompt_toolkit.history import FileHistory
    from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
    
    while 1:
        user_input = prompt('>', 
                            history=FileHistory('history.txt'),
                            auto_suggest=AutoSuggestFromHistory(),
                           )
        print(user_input)
    

    И научить автоподсказки определенным предустановленным командам.


    
    from prompt_toolkit import prompt
    from prompt_toolkit.history import FileHistory
    from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
    from prompt_toolkit.contrib.completers import WordCompleter
    
    SQLCompleter = WordCompleter(['select', 'from', 'insert', 'update', 'delete', 'drop'],
                                 ignore_case=True)
    
    while 1:
        user_input = prompt('SQL>', 
                            history=FileHistory('history.txt'),
                            auto_suggest=AutoSuggestFromHistory(),
                            completer=SQLCompleter,
                            )
        print(user_input)
    

    Либа крайне простая и дает возможность сделать свой классный и полностью кастомизируемый интерфейс.


    Зачем это?


    Внимательное отношение к, казалось бы, одноразовым программам позволит вам писать не код на выброс, а консольные инструменты, которые легко можно использовать повторно потом. Это экономит время и, конечно же, делает работу с вашими скриптами намного приятней.

    • +31
    • 9.1k
    • 7
    Support the author
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 7

      +3

      Мне подобных штук очень не хватало в Си, потиху пилил свой велосипед. Начиналось всё с кросплатформенного printf с цветом, а закончилось Winter Novel. Не забывайте вовремя остановиться! :-)

        0
        Мне больше всего нравится Click

        Хелловорлд
        import click
        
        @click.command()
        @click.option('--count', default=1, help='Number of greetings.')
        @click.option('--name', prompt='Your name',
                      help='The person to greet.')
        def hello(count, name):
            """Simple program that greets NAME for a total of COUNT times."""
            for x in range(count):
                click.echo('Hello %s!' % name)
        
        if __name__ == '__main__':
            hello()
        

        +1

        Классно, что есть такие штуки. В свое время искал библиотеку для консольного gui, но они все были ужасны. Не помню, на чем остановился, но в итоге из-за необходимости в мелких украшательствах код для отображения интерфейса занимал больше строк и потребовал больше времени, чем собственно вся остальная логика. После того случая изучение фронтенда уже не кажется пустой тратой времени


        Для cli есть очень неплохая библиотека от еще более крупной корпорации — google fire. Идеально интегрируется в любой код, работает удобно. Только вот из коробки нет возможности задавать однобуквенные алиасы (-v вместо --version) или я не разобрался как. Автодополнения вроде тоже не было
        Для cli

          0
          В качестве иллюстрации использования python-prompt-toolkit — на нем сделан симпатичный терминал для работы с Kubernetes под названием kube-shell. (Писал о нём в этом обзоре.)

          Что интересно, у этой утилиты вскоре появился конкурент на Go (kube-prompt), автор которой попутно «повторил» и саму библиотеку python-prompt-toolkit на том же Go — go-prompt. И она явно нашла своих пользователей (разработчиков) с 2300+ звёзд на GitHub и вот таким уже списком использующих её проектов.
            0

            За подборку спасибо. Действительно могут пригодиться. Даже знаю уже где попробую приткнуть.
            А вот для прошлых моих юзкейсов большинство этих библиотек были бы бесполезны, кроме fabric наверное.
            Правда я про него узнал когда активно уже использовал paramiko и connection pool, покрывая 10% нужной мне функциональности fabric без его удобства.


            Не писал я скриптов с интерактивом, они "запустил и забыл" все. И запускаются то из cron то из под CI/CD то вообще один скрипт другой пускает или использует из него функции.


            Так что наиболее важным всегда было написать внятный парсинг командной строки используя argparse или docopts.
            Второй момент по значимости — это держать в голове мысль что твой скрипт может быть использован и как модуль.
            Тогда сами по себе появляются классы/функции и мало-мальски оформленная архитектура.


            Так что не только в замечательных библиотеках дело.

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