Архивная библиотека Python: сохранение форматирования документации в сообщении помощи

При поиске более быстрых способов разбора аргументов командной строки в моих скриптах я наткнулся на библиотеку argh.

Мне действительно нравятся функции argh, но я столкнулся с одним недостатком, который мешает мне его использовать, и это связано с сообщением справки по умолчанию, которое отображается, если я вызываю опцию —help: по умолчанию строка документации функции отображается в верхней части списка аргументов. Это здорово, однако первоначальное форматирование потеряно. Смотрите, например, следующий пример сценария

import argh

def func(foo=1, bar=True):
    """Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.
    """
    print foo, bar

argh.dispatch_command(func, argv=['-h'])

что приведет к следующему выводу

usage: script.py [-h] [-f FOO] [-b]

Sample function. Parameters: foo: float An example argument. bar: bool Another
argument.

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO
  -b, --bar

Есть ли (простой) способ получить результат, подобный следующему?

usage: script.py [-h] [-f FOO] [-b]

Sample function.

    Parameters:
        foo: float
            An example argument.
        bar: bool
            Another argument.

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO
  -b, --bar

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

4 ответа

Решение

Я не знаком с arghно, видимо, это обертка argparse, Я думаю, что это берет на себя вашу функцию __doc__и делая это description парсера, например

parser = argparse.ArgumentParser(description=func.__doc__)

https://docs.python.org/2.7/library/argparse.html

argparse имеет RawDescriptionHelpFormatter который отображает описание как есть.

parser = argparse.ArgumentParser(description=func.__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter)

Итак, вопрос в том, есть ли способ получить argh использовать этот форматер?

это argparse Скрипт выдает помощь, которую вы хотите:

import argparse

def func(foo=1, bar=True):
    """Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.
    """
    print foo, bar

parser = argparse.ArgumentParser(prog='script.py',
    description=func.__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-f', '--foo', type=float)
parser.add_argument('-b', '--bar', action='store_false')
parser.print_help()

В argh/dispatching.py

def dispatch_command(function, *args, **kwargs):
    ...
    parser = argparse.ArgumentParser(formatter_class=PARSER_FORMATTER)
    set_default_command(parser, function)
    dispatch(parser, *args, **kwargs)

Таким образом, вы можете установить:

PARSER_FORMATTER = argparse.RawDescriptionHelpFormatter

или напишите свою собственную функцию:

def raw_dispatch_command(function, *args, **kwargs):
    ...
    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
    set_default_command(parser, function)
    dispatch(parser, *args, **kwargs)

С помощью @hpaulj мне наконец удалось получить желаемое поведение. Чтобы облегчить это, я определил пользовательский декоратор, похожий на argh.arg, с целью не писать @argh.arg(‘—param’, help=“%(default)s”) для каждого параметра отдельно, но вместо этого использовать только один @arg_custom() декоратор по моей функции:

def arg_custom():
    from argh.constants import ATTR_ARGS
    from argh.assembling import  _get_args_from_signature, _fix_compat_issue29

    def wrapper(func):
        declared_args = getattr(func, ATTR_ARGS, [])
        for a in list(_get_args_from_signature(func)):
             declared_args.insert(0, dict(option_strings=a['option_strings'], help="(default: %(default)s)"))
        setattr(func, ATTR_ARGS, declared_args)
        _fix_compat_issue29(func)
        return func
    return wrapper

Важным моментом здесь является то, что for цикл заботится о том, чтобы все аргументы получили соответствующие help=“%(default)s” вариант. Вместе с изменением соответствующих строк в argh/constants.py

class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
        pass
PARSER_FORMATTER = CustomFormatter

теперь мы можем удобно использовать

@arg_custom()
def func(foo=1, bar=True):
    """Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.
    """
    print foo, bar

argh.dispatch_command(func)

уступая наконец

usage: script.py [-h] [-f FOO] [-b]

Sample function.

        Parameters:
            foo: float
                An example argument.
            bar: bool
                Another argument.


optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO  (default: 1)
  -b, --bar          (default: True) 

при выполнении сценария с -h вариант.

Спасибо за ваш интерес к библиотеке Argh. Обсуждаемые здесь решения будут включены в следующий выпуск (argh ≥ 0,25). Смотрите также проблему № 64 (уже исправлена).

Что касается вопроса получения значений по умолчанию в справочных линиях, это argparse скрипт объединяет 2 класса форматера

import argparse

def func(foo=1, bar=True):
    ...
    """
    print foo, bar

class MyFormatter(argparse.RawDescriptionHelpFormatter,
    argparse.ArgumentDefaultsHelpFormatter):
    pass

parser = argparse.ArgumentParser(prog='script.py',
    description=func.__doc__,
    formatter_class=MyFormatter)
parser.add_argument('-f', '--foo', type=float, default=1, help='test')
parser.add_argument('-b', '--bar', action='store_false', help='test')
parser.print_help()

производства

usage: script.py [-h] [-f FOO] [-b]

Sample function.
   ...
optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO  test (default: 1)
  -b, --bar          test (default: True)

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

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

Если вы используете аннотации, вы даете $(default)s:

parser = argparse.ArgumentParser(prog='script.py',
    description=func.__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-f', '--foo', type=float, default=1, help='default: %(default)s')
parser.add_argument('-b', '--bar', action='store_false', help='default: %(default)s')
Другие вопросы по тегам