Как отформатировать справку по позиционным аргументам с помощью Python optparse?

Как упоминалось в документах, optparse.OptionParser использует IndentedHelpFormatter для вывода форматированной справки по параметрам, для которой я нашел несколько Документация по API.

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

Уточнение

Предпочтительно использовать только stdlib. Optparse отлично справляется, за исключением одного нюанса форматирования, который, как мне кажется, мы должны исправить, не импортируя все остальные пакеты. :-)


person cdleary    schedule 13.03.2009    source источник
comment
это настоящий позор, у меня сейчас такая же проблема.   -  person Matt Joiner    schedule 07.02.2010


Ответы (4)


Лучше всего было бы написать патч для модуля optparse. А пока вы можете сделать это с помощью слегка измененного класса OptionParser. Это не идеально, но это сделает то, что вы хотите.

#!/usr/bin/env python
from optparse import OptionParser, Option, IndentedHelpFormatter

class PosOptionParser(OptionParser):
    def format_help(self, formatter=None):
        class Positional(object):
            def __init__(self, args):
                self.option_groups = []
                self.option_list = args

        positional = Positional(self.positional)
        formatter = IndentedHelpFormatter()
        formatter.store_option_strings(positional)
        output = ['\n', formatter.format_heading("Positional Arguments")]
        formatter.indent()
        pos_help = [formatter.format_option(opt) for opt in self.positional]
        pos_help = [line.replace('--','') for line in pos_help]
        output += pos_help
        return OptionParser.format_help(self, formatter) + ''.join(output)

    def add_positional_argument(self, option):
        try:
            args = self.positional
        except AttributeError:
            args = []
        args.append(option)
        self.positional = args

    def set_out(self, out):
        self.out = out
def main():
    usage = "usage: %prog [options] bar baz"
    parser = PosOptionParser(usage)
    parser.add_option('-f', '--foo', dest='foo',
                      help='Enable foo')
    parser.add_positional_argument(Option('--bar', action='store_true',
                                   help='The bar positional argument'))
    parser.add_positional_argument(Option('--baz', action='store_true',
                                   help='The baz positional argument'))
    (options, args) = parser.parse_args()
    if len(args) != 2:
        parser.error("incorrect number of arguments")
    pass

if __name__ == '__main__':
    main()

И результат, который вы получите от запуска этого:

Usage: test.py [options] bar baz

  Options:
    -h, --help         show this help message and exit
    -f FOO, --foo=FOO  Enable foo

Positional Arguments:
  bar  The bar positional argument
  baz  The baz positional argument
person Douglas Mayle    schedule 20.03.2009
comment
Это было блестяще. Однако небольшой вопрос: можете ли вы определить, установлено ли использование пользователем или используется значение по умолчанию, и если да, добавьте позиционные аргументы в сообщение об использовании? - person UlfR; 01.12.2009
comment
Я предлагаю вам взглянуть на модуль argparse... Он достаточно мал, чтобы вы могли встроить его в любой проект, и делает то же самое, что и этот код, и многое другое... - person Douglas Mayle; 01.12.2009

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

person Richard Levasseur    schedule 13.03.2009
comment
Спасибо за указание, но я бы предпочел использовать stdlib, если это возможно. Это не кажется такой сложной проблемой, чтобы решить ее, поэтому я должен загрузить и связать целый пакет других опций, чтобы сделать это. - person cdleary; 13.03.2009
comment
argparse находится в стандартной библиотеке 2.7 - person fmark; 10.07.2010

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

Что я сделал, так это сгенерировал список небольших блоков документации для каждого из моих позиционных аргументов, используя \ts, чтобы получить правильный интервал. Затем я присоединил их к новой строке и добавил к строке «использование», которая передается в OptionParser.

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

Я посмотрел на методы OptionParser, исправляющие обезьяны, и помню (это было примерно год назад), что это было бы не так сложно, но я не хотел идти по этому пути.

person DNS    schedule 13.03.2009
comment
Да, я согласен с порядком, но мой текст использования дает имена позиционным аргументам, и я хочу, чтобы пары имя-объяснение выглядели одинаково в разделах «Аргументы» и «Параметры». - person cdleary; 13.03.2009

Большая часть текста справки для позиционных аргументов напоминает формат, часто используемый на справочных страницах для блоков *NIX. Взгляните на как задокументирована команда 'cp'. Ваш текст справки должен напоминать это.

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

person Jon W    schedule 13.03.2009
comment
Вы не можете указать справку для позиционных аргументов, если только я не упустил здесь что-то важное. Я хочу, чтобы он выглядел так же, как сгенерированный раздел «Параметры». Я думаю, что форматировать его вручную глупо, поэтому я, вероятно, напишу что-нибудь, чтобы сделать это для меня, если оно еще не существует. - person cdleary; 13.03.2009