Сообщить об ошибке.

Использование декоратора @click.option() при создании сценариев

Добавление опций к сценариям командной строки может быть выполнено с помощью декоратора @click.option(). Так как опции могут быть разных версий (короткие или длинные), существует множество параметров для настройки их поведения. Поведение опций сценария CLI, написанных при помощи click, отличаются от позиционных параметров.

Содержание:


Правила выбора имя опции для передачи в функцию.

У опции есть имя, которое будет использоваться в качестве имени аргумента, при вызове декорированной функции. Различные варианты имен опций передаются декоратору в качестве позиционных аргументов, например @click.option('-v', '--verbose').

Так как опции могут иметь сокращенное имя наряду с полным именем, а так же иметь один или два префикса - перед самим именем, модуль click определяет правила, согласно которым выбирается одно конкретное имя опции, которое будет передаваться в качестве аргумента основной функции.

Имя опции выбирается в следующем порядке:

  • Если имя не имеет префикса, то оно используется как имя аргумента Python и не рассматривается как имя опции в командной строке.
  • Если есть хотя бы одно имя с двумя префиксами --, то в качестве имени используется первое заданное имя.
  • В противном случае используется первое имя с префиксом из одного -.

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

Рассмотрим выбор имени опции на примере:

@click.command()
@click.option('-s', '--string-to-echo')
# выбирается имя с двумя тире
def echo(string_to_echo):
    click.echo(string_to_echo)

@click.command()
@click.option('-s', '--string-to-echo', 'string')
# выбирается имя без тире
def echo(string):
    click.echo(string)

Еще примеры выбора имени опции для аргумента функции:

  • если @click.option("-f", "--foo-bar"), то имя для аргумента будет выбрано foo_bar;
  • если @click.option("-x"), то имя для аргумента будет выбрано x;
  • если @click.option("-f", "--имя файла", "dest"), то имя для аргумента будет выбрано dest;
  • если @click.option("--camelCase"), то имя для аргумента будет выбрано camelcase;
  • если @click.option("-f", "-fb"), то имя для аргумента будет выбрано f;
  • если @click.option("--f", "--foo-бар"), то имя для аргумента будет выбрано f;
  • если @click.option("---f"), то имя для аргумента будет выбрано _f.

Базовое использование опции в сценарии командной строки.

В самом простом случае, опции командной строки могут принимать аргумент, который является значением. Если тип опции не указан, то используется тип значения по умолчанию default. Если в декораторе @click.option() аргумент default не задан, то предполагается, что это тип str.

import click

@click.command()
@click.option('-x')
@click.option('-y', default=1)
@click.option('-z', default=1.0)
def test(x, y, z):
    click.echo(f'x = {x} ({type(x)})')
    click.echo(f'y = {y} ({type(y)})')
    click.echo(f'z = {z} ({type(z)})')

if __name__ == '__main__':
    test()

При запуске этот сценарий выведет следующие результаты:

$ python3 test.py -x 5 -y 7 -z 9 
# x = 5 (<class 'str'>)
# y = 7 (<class 'int'>)
# z = 9.0 (<class 'float'>)

Чтобы отображать значения по умолчанию default на странице справки, необходимо передавать аргумент show_default=True

import click

@click.command()
@click.option('--n', default=1, show_default=True)
def test(n):
    click.echo('.' * n)

if __name__ == '__main__':
    test()

Вывод сценария:

$ python3 test.py --help
# Usage: test [OPTIONS]
# 
# Options:
#   --n INTEGER  [default: 1]
#   --help       Show this message and exit.

Параметры по умолчанию можно не указывать, но чтобы сделать опцию обязательной, необходимо передать required=True в качестве аргумента декоратору @click.option().

@click.command()
# указываем тип значения и 
# делаем опцию обязательной
@click.option('--n', required=True, type=int)
def dots(n):
    click.echo('.' * n)

Опции, которые позволяют указать несколько значений.

Бывают ситуации, когда необходимо, чтобы опция командной строки принимала более одного аргумента. Количество принимаемых значений можно настроить с помощью аргумента nargs декоратора @click.option(). Все переданные значения опции сохраняются в виде кортежа.

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

@click.command()
@click.option('--pos', nargs=2, type=float)
def test(pos):
    a, b = pos
    click.echo(f"{a} / {b}")

Вывод сценария:

$ python3 test.py --pos 2.0 3.0
# 2.0 / 3.0

Кортежи как многозначные опции

При использовании аргумента nargs, установленного на определенное число, каждый элемент в результирующем кортеже имеет один и тот же тип. Такое поведение не удобно, если необходимо использовать разные типы для разных элементов кортежа. Что бы использовать разные типы, можно напрямую указать кортеж, как значение аргумента type:

@click.command()
@click.option('--item', type=(str, int))
def test(item):
    name, id = item
    click.echo(f"name={name} id={id}")

Вывод сценария:

$ python3 test.py --item peter 1338
# name=peter id=1338

При использовании кортежа в качестве значения type, для аргумента nargs автоматически устанавливается длина кортежа, и автоматически используется тип click.Tuple. Таким образом, приведенный выше пример эквивалентен следующему:

@click.command()
@click.option('--item', nargs=2, type=click.Tuple([str, int]))
def putitem(item):
    name, id = item
    click.echo(f"name={name} id={id}")

Опции, которые могут повторятся.

Как и в случае с nargs, существует также случай, когда требуется поддерживать опцию, которая может указываться несколько раз, и использовать все переданные ей значения, а не только последнее. Например, git commit -m foo -m bar будет записывать две строки для commit: foo и bar. Такое поведение может быть смоделировано с помощью флага multiple, который указывается в качестве аргумента @click.option():

@click.command()
@click.option('--message', '-m', multiple=True)
def test(message):
    click.echo('\n'.join(message))

Вывод сценария:

$ python3 test.py -m foo -m bar
# foo
# bar

При передаче значения аргумента default вместе с аргументом multiple=True значение по умолчанию default должно быть списком или кортежем, иначе оно будет интерпретировано как список отдельных символов.

@click.option("--format", multiple=True, default=["json"])

Подсчет повторяющихся опций.

В некоторых очень редких случаях интересно использовать повторение опций для подсчета целого числа. Такое поведение опции использует, например, система управления конфигурациями ansible для более подробного вывода логов:

@click.command()
@click.option('-v', '--verbose', count=True)
def log(verbose):
    click.echo(f"Verbosity: {verbose}")

Вывод сценария:

$ python3 log.py -vvv
# Verbosity: 3

Использование опции, как логических флагов.

Логические флаги - это опции, которые включают или отключают какое то поведение сценария. Такое поведение может быть выполнено путем определения двух флагов за один раз, разделенных косой чертой / для включения или отключения параметра. Если косая черта встречается в строке опции, то модуль click автоматически распознает, что это логический флаг, и неявно передаст аргумент is_flag=True.

import sys

@click.command()
@click.option('--shout/--no-shout', default=False)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

Вывод сценария:

$ python3 info.py --shout
# LINUX!!!!111

$ info --no-shout
# linux

$ info
# linux

Если сценарию не нужна явная передача '--no-shout', то можно просто определить опцию '--shout' и вручную сообщить @click.option(), что она является флагом is_flag=True:

import sys

@click.command()
@click.option('--shout', is_flag=True)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

Вывод сценария:

$ python3 info.py --shout
# LINUX!!!!111

$ info
# linux

Обратите внимание, что если косая черта уже содержится в опции (например, если использовать параметры в стиле Windows, где / - символ префикса), то можно альтернативно разделить параметры символом ;:

@click.command()
@click.option('/debug;/no-debug')
def log(debug):
    click.echo(f"debug={debug}")

if __name__ == '__main__':
    log()

Если нужно определить псевдоним только для второго варианта, то необходимо будет использовать ведущие пробелы ' /alias', чтобы устранить неоднозначность строки формата:

@click.command()
@click.option('--shout/--no-shout', ' /-S', default=False)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

Вывод сценария:

$ python3 test.py --help
# Usage: info [OPTIONS]
# 
# Options:
#   --shout / -S, --no-shout
#   --help                    Show this message and exit.

Поведение опции, как переключателя.

Помимо использования опций, как логических флагов, есть также опции-переключатели. Они реализуются путем установки нескольких опций для одного и того же имени аргумента, передаваемого в функцию, тем самым определяя значения флага. Обратите внимание, что передавая аргумент flag_value в @click.option(), модуль click неявно устанавливает дополнительно аргумент is_flag=True.

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

import sys

@click.command()
@click.option('--upper', 'transformation', flag_value='upper',
              default=True)
@click.option('--lower', 'transformation', flag_value='lower')
def info(transformation):
    click.echo(getattr(sys.platform, transformation)())

Вывод сценария:

$ python3 info.py --upper
# LINUX

$ info --lower
# linux

$ info
# LINUX

Выбор опции из списка допустимых значений.

Иногда необходимо, чтобы опция представляла собой выбор из списка определенных значений. В этом случае можно использовать тип click.Choice. Его можно создать со списком допустимых значений, например: type=click.Choice(['MD5', 'SHA1']. В декорированную функцию будет передан соответствующий вариант из списка допустимых значений, а не строка, переданная опции в качестве значения.

@click.command()
@click.option('--hash-type',
              type=click.Choice(['MD5', 'SHA1'], case_sensitive=False))
def digest(hash_type):
    click.echo(hash_type)

Аргумент case_sensitive=False, переданный в декоратор @click.option(), проверяет наличие переданного значения опции в списке допустимых значения без учета регистра.

Вывод сценария:

$ python3 digest.py --hash-type=MD5
# MD5

$ digest --hash-type=md5
# MD5

$ digest --hash-type=foo
# Usage: digest [OPTIONS]
# Try 'digest --help' for help.
# 
# Error: Invalid value for '--hash-type': 'foo' is not one of 'MD5', 'SHA1'.

$ digest --help
# Usage: digest [OPTIONS]
# 
# Options:
#   --hash-type [MD5|SHA1]
#   --help                  Show this message and exit.

Создавайте варианты для выбора только в виде списка или кортежа. Другие итерации (например, генераторы) могут привести к неожиданным результатам.

Варианты выбора работают с опциями, у которых multiple=True. Если задан аргумент default совместно с аргументом multiple=True, то это должен быть список или кортеж допустимых вариантов.

Выбор должен быть уникальным, если передается аргумент case_sensitive.

Выбор из диапазона числовых значений.

Тип click.IntRange расширяет тип int, и гарантирует, что значение опции содержится в заданном диапазоне. Тип click.FloatRange делает то же самое для типа float.

Синтаксис:

click.IntRange(min=None, max=None, min_open=False, max_open=False, clamp=False)
click.FloatRange(min=None, max=None, min_open=False, max_open=False, clamp=False)

Если аргументы min или max опущены, то в этом направлении могут приниматься любые (неограниченные) значения. По умолчанию, граничное значение входит в допустимый диапазон. Аргументы min_open и max_open могут использоваться для исключения этой границы из диапазона.

Если режим фиксации clamp включен, то значение, выходящее за пределы диапазона, устанавливается на границу, вместо генерирования ошибки. Например, диапазон IntRange(0, 5) вернет 5, для значения опции 10 или 0 для значения опции -1. При использовании click.FloatRange, режим фиксации clamp можно включить, если только обе границы диапазона имеют значения.

@click.command()
@click.option("--count", type=click.IntRange(0, 20, clamp=True))
@click.option("--digit", type=click.IntRange(0, 9))
def test(count, digit):
    click.echo(str(digit) * count)

Вывод сценария:

$ python3 test --count=100 --digit=5
# 55555555555555555555

$ python3 test --count=6 --digit=12
# Usage: test [OPTIONS]
# Try 'test --help' for help.
# 
# Error: Invalid value for '--digit': 12 is not in the range 0<=x<=9.

Интерактивный ввод некоторых опций.

В некоторых случаях требуются такие опции, которые могут запрашивать пользовательский ввод из командной строки, если конечно они не указаны или не заданы по умолчанию. Такое поведение можно реализовать, указав аргумент prompt=True.

@click.command()
@click.option('--name', prompt=True)
def hello(name):
    click.echo(f"Hello {name}!")

Вывод сценария:

$ python3 hello.py --name=John
# Hello John!

$ hello
# Name: John
# Hello John!

Если необходимо изменить строку приглашения по умолчанию, то это можно сделать, передав требуемый текст в аргумент prompt:

@click.command()
@click.option('--name', prompt='Your name please')
def hello(name):
    click.echo(f"Hello {name}!")

Вывод сценария:

$ python3 test.py
# Your name please: John
# Hello John!

НЕ рекомендуется использовать аргумент приглашения prompt совместно с аргументом multiple=True.

По умолчанию пользователю будет предложено ввести данные, если они не были переданы через командную строку. Чтобы отключить это поведение, смотрите подраздел "Необязательное значение".

Запрашиваемый ввод пароля в сценарии.

Модуль click также поддерживает скрытый ввод данных при интерактивном режиме, а так же запрос подтверждения введенных данных. Такое поведение полезно для ввода пароля:

import codecs

@click.command()
@click.option(
    "--password", prompt=True, hide_input=True,
    confirmation_prompt=True
)
def encode(password):
    click.echo(f"encoded: {codecs.encode(password, 'rot13')}")

Вывод сценария:

$ python3 encode.py
# Password: 
# Repeat for confirmation: 
# encoded: frperg

Так как эта комбинация параметров довольно распространена, ее также можно заменить декоратором @click.password_option():

@click.command()
@click.password_option()
def encrypt(password):
    click.echo(f"encoded: to {codecs.encode(password, 'rot13')}")

Динамические значения по умолчанию для интерактивного ввода опции.

Аргументы auto_envvar_prefix и default_map используемые в контексте, позволяют программе считывать значения опций из окружения или файла конфигурации. Но такое поведение переопределяет действие аргумента prompt=True. Если, например, переменная окружения существует, но не имеет значения, то пользователь не может в интерактивном режиме изменить ее значение.

@click.command()
@click.option('--username', prompt=True)
def greet(username):
    click.echo(f'Hello {username}!')

if __name__ == '__main__':
    greet(auto_envvar_prefix='GREETER')
$ export GREETER_USERNAME
$ python3 greet.py
# Hello !

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

import os

@click.command()
@click.option(
    "--username", prompt=True,
    default=lambda: os.environ.get("USER", "")
)
def hello(username):
    click.echo(f"Hello, {username}!")

Чтобы описать значение по умолчанию в подсказке, установите его в show_default.

import os

@click.command()
@click.option(
    "--username", prompt=True,
    default=lambda: os.environ.get("USER", ""),
    show_default="current user"
)
def hello(username):
    click.echo(f"Hello, {username}!")

Вывод сценария:

$ python3 hello.py --help
# Usage: hello [OPTIONS]
# 
# Options:
#   --username TEXT  [default: (current user)]
#   --help           Show this message and exit.

Обратные вызовы.

Иногда нужна такая опция, которая полностью изменяет поток выполнения сценария. Например, это тот случай, когда нужно просто вывести версию приложения, а затем его закрыть. Например в стиле опции --version.

Примечание. Фактическая реализация многократно используемого параметра --version доступна в модуле click как функция click.version_option(). Приведенный в подразделе код - это просто пример того, как реализовать такой флаг.

В таких случаях понадобятся две концепции: активные опции и обратный вызов. Активная опция - это опция, которая обрабатывается раньше других, а обратный вызов - это то, что выполняется после обработки опции. Так же необходимо, чтобы активная опция не вызывала сообщения об ошибке.

Обратный вызов - это функция, которая вызывается с двумя параметрами: текущим контекстом и значением. Контекст предоставляет некоторые полезные функции, такие как выход из приложения и дает доступ к другим уже обработанным параметрам.

Пример кода, реализующего флаг --version:

import click

def print_version(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    click.echo('Version 1.0')
    ctx.exit()

@click.command()
@click.option('--version', is_flag=True, callback=print_version,
              expose_value=False, is_eager=True)
@click.option('--echo', is_flag=True)

def test(echo):
    if echo:
        click.echo('Hello World!')


if __name__ == '__main__':
    test()

Аргумент expose_value=False предотвращает передачу довольно бессмысленной опции version как аргумента в функцию hello(). Если его не указывать, то сценарию будет передано логическое значение. Флаг resilient_parsing применяется к контексту ctx, если нужно проанализировать командную строку без какого-либо деструктивного поведения, которое могло бы изменить поток выполнения.

$ python3 test.py --echo
# Hello World!

$ python3 test.py --version
# Version 1.0

$ python3 test.py --echo --version
# Version 1.0

Создание опции со значениями yes/no.

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

def abort_if_false(ctx, param, value):
    if not value:
        ctx.abort()

@click.command()
@click.option('--yes', is_flag=True, callback=abort_if_false,
              expose_value=False,
              prompt='Are you sure you want to drop the db?')
def dropdb():
    click.echo('Dropped all tables!')

Вывод сценария:

$ python3 dropdb.py  
# Are you sure you want to drop the db? [y/N]: n
# Aborted!

$ dropdb --yes
# Dropped all tables!

Поскольку эта комбинация параметров довольно распространена, ее также можно заменить декоратором click.confirm_option():

@click.command()
@click.confirmation_option(prompt='Are you sure you want to drop the db?')
def dropdb():
    click.echo('Dropped all tables!')

Использование обратного вызова для проверки/валидации значения.

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

В сlick 1.0 можно вызвать исключение только UsageError, но, начиная с версии click 2.0, также можно вызвать BadParameter, которое имеет дополнительное преимущество: сообщение об ошибке будет автоматически форматироваться с именем опции.

# функция проверки
def validate_rolls(ctx, param, value):
    if isinstance(value, tuple):
        return value
    try:
        rolls, _, dice = value.partition("d")
        return int(dice), int(rolls)
    except ValueError:
        raise click.BadParameter("format must be 'NdM'")

@click.command()
@click.option(
    "--rolls", type=click.UNPROCESSED, callback=validate_rolls,
    default="1d6", prompt=True,
)
def roll(rolls):
    sides, times = rolls
    click.echo(f"Rolling a {sides}-sided dice {times} time(s)")

Вывод сценария:

$ python3 roll.py  --rolls=42
# Usage: roll [OPTIONS]
# Try 'roll --help' for help.
# 
# Error: Invalid value for '--rolls': format must be 'NdM'

$ python3 roll.py --rolls=2d12
# Rolling a 12-sided dice 2 time(s)

$ python3 roll.py
# Rolls [1d6]: 42
# Error: format must be 'NdM'
# Rolls [1d6]: 2d12
# Rolling a 12-sided dice 2 time(s)

Подстановка значений опций из environment.

Очень полезной функцией модуля click является возможность принимать значения опций из переменных среды environment в дополнение к передаче значений обычным способом, через командную строку. Это значительно упрощает автоматизацию инструментов. Например, можно передать файл конфигурации с опцией --config, и в то же время поддерживать экспорт пары ключ-значение TOOL_CONFIG=hello.cfg для более удобной разработки.

Такое поведение модуль click поддерживает двумя способами. Первый из них - автоматически создавать переменные среды, которые поддерживаются только для опций. Чтобы включить эту функцию, необходимо передать параметр auto_envvar_prefix в вызываемый скрипт. Затем каждая подкоманда и опция добавляются в виде переменной, разделенной символом подчеркивания в верхнем регистре. Например, если у сценария есть подкоманда run с опцией --reload и префиксом WEB, тогда переменная окружения будет выглядеть как WEB_RUN_RELOAD.

@click.command()
@click.option('--username')
def greet(username):
    click.echo(f'Hello {username}!')

if __name__ == '__main__':
    greet(auto_envvar_prefix='GREETER')

Вывод сценария:

$ export GREETER_USERNAME=john
$ python3 greet.py  
# Hello john!

При использовании auto_envvar_prefix с группами команд имя подкоманды должно быть включено в переменную среды между префиксом и именем опции, то есть PREFIXCOMMANDVARIABLE. Например, если есть подкоманда run-server, принимающая опцию --host и префикс WEB, тогда переменная будет выглядеть следующим образом: WEB_RUN_SERVER_HOST.

# используем группу команд
@click.group()
@click.option('--debug/--no-debug')
def test(debug):
    click.echo(f"Debug mode is {'on' if debug else 'off'}")

# подкоманда `greet` сценария `test`
@cli.command()
@click.option('--username')
def greet(username):
    click.echo(f"Hello {username}!")

if __name__ == '__main__':
    test(auto_envvar_prefix='GREETER')

Вывод сценария:

# экспортируем переменные
$ export GREETER_DEBUG=false
$ export GREETER_GREET_USERNAME=John

# запускаем сценарий
$ python3 test.py  greet
# Debug mode is off
# Hello John!

Второй вариант - вручную получить значения из определенных переменных среды, указав имя переменной среды в аргументе envvar декоратора @click.option().

@click.command()
@click.option('--username', envvar='USERNAME')
def greet(username):
   click.echo(f"Hello {username}!")

if __name__ == '__main__':
    greet()

Вывод сценария:

$ export USERNAME=john
$ python3 greet.py
# Hello john!

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

Передача нескольких значений опции из environment.

Так как опции могут принимать несколько значений, то получение таких значений из переменных среды (которые являются строками) немного сложнее. Модуль click решает эту проблему, предоставляя типу настраивать это поведение. Как для аргументов multiple, так и для nargs со значениями, отличными от 1, click вызовет метод ParamType.split_envvar_value() для выполнения деления строки, переданной из переменных среды в качестве значения опции.

Реализация по умолчанию для всех типов значений - деление происходит по пробелам. Исключениями из этого правила являются типы файлов и пути, которые делятся в соответствии с правилами разделения путей операционной системы. В системах Unix, таких как Linux и OS X, разделение происходит для каждого двоеточия :, а для Windows - каждой точки с запятой ;.

@click.command()
@click.option('paths', '--path', envvar='PATHS', multiple=True,
              type=click.Path())
def test(paths):
    for path in paths:
        click.echo(path)

if __name__ == '__main__':
    test()

Вывод сценария:

$ export PATHS=./foo/bar:./test
$ python3 test.py  
# ./foo/bar
# ./test

Использование других префиксных символов в опции.

Модуль click может работать с альтернативными префиксными символами для опций, а не только -. Такое поведение, например, полезно, если нужно обрабатывать косые черты / как опции или что-то подобное. Обратите внимание, что в целом это настоятельно не рекомендуется, потому что разработчики должны придерживались семантики POSIX. Однако в определенных ситуациях это может быть полезно:

@click.command()
@click.option('+w/-w')
def chmod(w):
    click.echo(f"writable={w}")

if __name__ == '__main__':
    chmod()

Вывод сценария:

$ python3 chmod.py +w
# writable=True

$ python3 chmod.py -w
# writable=False

Обратите внимание, что если использовать косую черту / в качестве префиксного символа, и а так же нужен этой опции логический флаг, то необходимо отделить его символом ; вместо /:

@click.command()
@click.option('/debug;/no-debug')
def log(debug):
    click.echo(f"debug={debug}")

if __name__ == '__main__':
    log()

Необязательная передача значения опции.

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

Установка is_flag=False, flag_value=value сообщает модулю click, что опции все еще можно передать значение, но если задан только флаг, используется flag_value.

@click.command()
@click.option("--name", is_flag=False, flag_value="Flag", default="Default")
def hello(name):
    click.echo(f"Hello, {name}!")

Вывод сценария:

$ python3 hello.py
# Hello, Default!

$ python3 hello.py --name Value
# Hello, Value!

$ python3 hello.py --name
# Hello, Flag!

Если для опции включена подсказка (аргумент prompt декоратора @click.option()), то установка аргумента prompt_required=False указывает модулю показывать подсказку только в том случае, если задан флаг опции, а не в том случае, если опция вообще не указывается.

@click.command()
@click.option('--name', prompt=True, prompt_required=False, default="Default")
def hello(name):
    click.echo(f"Hello {name}!")

Вывод сценария:

$ python3 hello.py
# Hello Default!

$ python3 hello.py --name Value
# Hello Value!

$ python3 hello.py --name
# Name [Default]: