Python Click: пользовательское сообщение об ошибке

Я использую отличный Python Нажмите библиотека для обработки параметров командной строки в мой инструмент. Вот упрощенная версия моего кода (полный скрипт здесь):

@click.command(
    context_settings = dict( help_option_names = ['-h', '--help'] )
)
@click.argument('analysis_dir',
                 type = click.Path(exists=True),
                 nargs = -1,
                 required = True,
                 metavar = "<analysis directory>"
)

def mytool(analysis_dir):
   """ Do stuff """

if __name__ == "__main__":
    mytool()

если кто-то выполняет команду без каких-либо флагов, они получают сообщение об ошибке по умолчанию:

$ mytool

Usage: mytool [OPTIONS] <analysis directory>

Error: Missing argument "analysis_dir".

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

существует ли простой способ сделать это? Я знаю, что могу удалить required атрибут и обрабатывать эту логику в основной функции, но это чувствует себя как-то хаки для такого незначительного добавления.

1 ответов


построение сообщений для большинства ошибок в python-click обрабатывается методом show класса UsageError:click.exceptions.UsageError.show.

Итак, если вы переопределите этот метод, вы сможете создать свое собственное настраиваемое сообщение об ошибке. Ниже приведен пример настройки, которая добавляет меню справки к любому сообщению об ошибке, которое отвечает на это и:

def modify_usage_error(main_command):
    '''
        a method to append the help menu to an usage error

    :param main_command: top-level group or command object constructed by click wrapper 
    :return: None
    '''

    from click._compat import get_text_stderr
    from click.utils import echo
    def show(self, file=None):
        import sys
        if file is None:
            file = get_text_stderr()
        color = None
        if self.ctx is not None:
            color = self.ctx.color
            echo(self.ctx.get_usage() + '\n', file=file, color=color)
        echo('Error: %s\n' % self.format_message(), file=file, color=color)
        sys.argv = [sys.argv[0]]
        main_command()

    click.exceptions.UsageError.show = show

после определения основной команды можно запустить модификатор сценарий:

import click
@click.group()
def cli():
    pass

modify_usage_error(cli)

Я не исследовал, существуют ли вызовы clickexception во время выполнения, кроме ошибок использования. Если есть, то вам может потребоваться изменить пользовательский обработчик ошибок, чтобы сначала проверить, что ctx является атрибутом, прежде чем добавлять строку click.exceptions.ClickException.show = show так как не появляется, что ClickException подается ctx при инициализации.