С того дня, как я начал изучать и работать с Python, argparse был де-факто модулем для написания CLI (Ccommand Line I интерфейс) скрипты. Однако недавно я наткнулся на другой пакет Python, который очень просто помогает в создании CLI-скриптов: Click (Ccommand Line Iинтерфейс Ссоздание Kэто).
О чем не эта статья
Это не сравнение между argparse и click или любым другим модулем, который позволяет реализовать интерфейс командной строки в Python.
О чем эта статья
Мы увидим, как создать простой интерфейс командной строки, используя возможности click.
Пойдем!
Монтаж
Обычное дело. Просто pip install click
и все готово.
Как правило, рекомендуется использовать виртуальную среду, чтобы иметь хорошее разделение между различными средами Python, а не загромождать одну среду множеством пакетов, которые могут вам не понадобиться во всех приложениях.
Сначала запустите pip install virtualenv
, чтобы установить пакет. Затем создайте новую папку для нашего маленького скрипта и создайте внутри виртуальную среду venv
:
$ mkdir clickdemo $ cd clickdemo $ virtualenv venv
А теперь просто активируйте новую среду. В Mac OS X или Linux:
$ . venv/bin/activate
В Windows:
$ venv\scripts\activate
Теперь вы увидите, что имя среды указано в вашем терминале.
(venv) $
затем мы можем установить click внутри нашей новой среды, запустив pip install click
.
Основной пример
Давайте реализуем скрипт clickdemo.py
, который просто говорит «Привет!»
#clickdemo.py import click @click.command() def greet(): print("Hello!") if __name__ == '__main__': greet()
Теперь запускаем его и проверяем вывод:
(venv) $ python clickdemo.py Hello!
Очень просто.
Одна из замечательных особенностей клика заключается в том, что он автоматически генерирует справочное сообщение для вашего скрипта:
(venv) $ python clickdemo.py --help Usage: clickdemo.py [OPTIONS] Options: --help Show this message and exit.
И обновить справочное сообщение так же просто, просто добавьте строку документации в свою командную функцию:
@click.command() def greet(): """Greetings stranger!""" print("Hello")
Теперь попробуем еще раз:
(venv) $ python clickdemo.py --help Usage: clickdemo.py [OPTIONS] Greetings stranger! Options: --help Show this message and exit.
Прохладный! Теперь у нас есть общее представление о том, как создать простой сценарий командной строки. Как насчет добавления некоторых параметров?
Дополнительные параметры
А.к.а.. ну .. Варианты.
Мы хотим, чтобы пользователи по желанию указывали свое имя и возраст.
@click.command() @click.option('--name', '-n', default='Stranger', type=click.STRING, help="Your name", show_default=True) @click.option('-a', '--age', default=None, type=int, help="Your age") def greet(name, age): """Greetings stranger!""" print(f"Hello {name}!") if age is not None: print(f"You are {age} years old.")
Несколько вещей, на которые следует обратить внимание:
- Вы можете указать значение по умолчанию для вашего параметра, а также тип
- Установка флага
show_default
покажет значение по умолчанию в справочном сообщении. - Нам нужно создать новый аргумент Python в украшенной функции для каждого параметра, который мы задаем в командной строке.
Когда дело доходит до именования этих аргументов, следует помнить о некоторых моментах:
- Если имя не имеет префикса, оно используется как имя аргумента Python и не обрабатывается как имя параметра в командной строке.
- Если имеется хотя бы одно имя с префиксом из двух дефисов, в качестве имени используется первое указанное имя.
- В противном случае используется имя с префиксом в один тире.
Ммм хорошо, что это значит? Давайте рассмотрим несколько примеров:
@click.option('-n', '--name') -> Function argument name: `name` @click.option('-n') -> Function argument name: `n` @click.option('-n', '--name', 'username') -> Function argument name: `username` @click.option('--UserName') -> Function argument name: `username` @click.option('--name', '--alternative') -> Function argument name: `name` @click.option('-n', '-nm') -> Function argument name: `n` @click.option('---name') -> Function argument name: `_name`
Мы можем добавить логические флаги с одним значением, установив is_flag=True
:
@click.command() @click.option('--name', '-n', default='Stranger', type=click.STRING, help="Your name", show_default=True) @click.option('-a', '--age', default=None, type=int, help="Your age") @click.option('-j', 'jedi', is_flag=True, default=False, help="Are you a Jedi Master?") def greet(name, age, jedi): """Greetings stranger!""" greeting = f"Hello Master {name}!" if jedi else f"Hello {name}!" print(greeting) if age is not None: print(f"You are {age} years old.")
Существует еще один способ указания логических флагов путем одновременного определения двух флагов, разделенных символом /
. Итак, последний пример будет выглядеть так:
@click.command() @click.option('--name', '-n', default='Stranger', type=click.STRING, help="Your name", show_default=True) @click.option('-a', '--age', default=None, type=int, help="Your age") @click.option('--jedi/--not-jedi', default=False, help="Are you a Jedi Master?") def greet(name, age, jedi): """Greetings stranger!""" greeting = f"Hello Master {name}!" if jedi else f"Hello {name}!" print(greeting) if age is not None: print(f"You are {age} years old.")
И вот как мы будем его использовать:
(venv) $ python clickdemo.py -n Anakin --not-jedi Hello Anakin!
Существует множество других функций, которые вы можете использовать, таких как несколько вариантов, подсчет, выбор и т. д. Я рекомендую вам ознакомиться с ними в документации по параметрам.
Обязательные параметры
А.к.а Аргументы.
Иногда мы хотим иметь обязательные позиционные аргументы в нашем скрипте. Например, запись вывода в файл. Давайте посмотрим, как этого добиться:
@click.command() @click.option('--name', '-n', default='Stranger', type=click.STRING, help="Your name", show_default=True) @click.option('-a', '--age', default=None, type=int, help="Your age") @click.option('--jedi/--not-jedi', default=False, help="Are you a Jedi Master?") @click.argument('filename', type=click.STRING) def greet(name, age, jedi, filename): """Greetings stranger!""" greeting = f"Hello Master {name}!" if jedi else f"Hello {name}!" print(greeting) if age is not None: print(f"You are {age} years old.") print(f"The output will be saved to {filename})
Затем аргумент можно указать в командной строке следующим образом:
(venv) $ python clickdemo.py -n Anakin --not-jedi output.txt Hello Anakin! Your output will be saved to output.txt
Click обрабатывает для нас чтение и запись в файлы через тип click.File
. Нам просто нужно указать, хотим ли мы открыть файл для чтения r
или для записи w
.
@click.command() @click.option('--name', '-n', default='Stranger', type=click.STRING, help="Your name", show_default=True) @click.option('-a', '--age', default=None, type=int, help="Your age") @click.option('--jedi/--not-jedi', default=False, help="Are you a Jedi Master?") @click.argument('input', type=click.File('r')) @click.argument('output', type=click.File('w')) def greet(name, age, jedi, input, output): """Greetings stranger!""" greeting = f"Hello Master {name}!" if jedi else f"Hello {name}!" print(greeting) if age is not None: print(f"You are {age} years old.") info = input.read() output.write(info)
Тестирование в командной строке:
python3 clickdemo.py -n Anakin --not-jedi -- - output.txt Hello Anakin! test one line and another one
Здесь мы принимаем ввод из командной строки, указав -
в качестве входного аргумента и записывая его обратно в output.txt
. Обратите внимание, что здесь мы определили параметры командной строки по-другому, используя строку --
для разделения списка параметров и списка аргументов.
Подробнее об Аргументах читайте в Документации по аргументам.
Click имеет много других интересных возможностей, которые упрощают реализацию сценариев CLI. Я рекомендую прочитать официальную документацию и попробовать поэкспериментировать с различными функциями.
И это обертка. Спасибо, что дошли до конца.
До следующего раза!