Управлять форматированием списка аргументов справки argparse?

import argparse
parser = argparse.ArgumentParser(prog='tool')
args = [('-u', '--upf', 'ref. upf', dict(required='True')),
        ('-s', '--skew', 'ref. skew', {}),
        ('-m', '--model', 'ref. model', {})]
for args1, args2, desc, options in args:  
     parser.add_argument(args1, args2, help=desc, **options)

parser.print_help()

Выход:

usage: capcheck [-h] -u UPF [-s SKEW] [-m MODEL]

optional arguments:
  -h, --help            show this help message and exit
  -u UPF, --upf UPF     ref. upf
  -s SKEW, --skew SKEW  ref. skew
  -m MODEL, --model MODEL
                        ref. model

Как распечатать ref. model в той же строке, что и -m MODEL, --model MODEL, а не в отдельной строке, когда я запускаю скрипт с параметром -h?


person Kaushik Balamukundhan    schedule 28.03.2011    source источник


Ответы (4)


Вы можете указать formatter_class аргумент:

parser = argparse.ArgumentParser(prog='tool',
  formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=27))

args = [('-u', '--upf', 'ref. upf', dict(required='True')),
        ('-s', '--skew', 'ref. skew', {}),
        ('-m', '--model', 'ref. model', {})]
for args1, args2, desc, options in args:  
     parser.add_argument(args1, args2, help=desc, **options)

parser.print_help()

Примечание. Реализация argparse.HelpFormatter является закрытой, только имя является общедоступным. Поэтому код может перестать работать в будущих версиях argparse. Отправьте запрос функции, чтобы предоставить общедоступный интерфейс для настройки max_help_position на http://bugs.python.org/

Выход

usage: tool [-h] -u UPF [-s SKEW] [-m MODEL]

optional arguments:
  -h, --help               show this help message and exit
  -u UPF, --upf UPF        ref. upf
  -s SKEW, --skew SKEW     ref. skew
  -m MODEL, --model MODEL  ref. model
person jfs    schedule 28.03.2011

Вдохновленный ответом @jfs, я придумал это решение:

def make_wide(formatter, w=120, h=36):
    """Return a wider HelpFormatter, if possible."""
    try:
        # https://stackoverflow.com/a/5464440
        # beware: "Only the name of this class is considered a public API."
        kwargs = {'width': w, 'max_help_position': h}
        formatter(None, **kwargs)
        return lambda prog: formatter(prog, **kwargs)
    except TypeError:
        warnings.warn("argparse help formatter failed, falling back.")
        return formatter

Имея это, вы можете вызвать его с любым HelpFormatter, который вам нравится:

parser = argparse.ArgumentParser(
    formatter_class=make_wide(argparse.ArgumentDefaultsHelpFormatter)
)

or

parser = argparse.ArgumentParser(
    formatter_class=make_wide(argparse.HelpFormatter, w=140, h=20)
)

Это гарантирует, что более широкий модуль форматирования действительно может быть создан с использованием аргументов width и max_help_position. Если частный API изменяется, это отмечается make_wide TypeError, а средство форматирования возвращается без изменений. Это должно сделать код более надежным для развернутых приложений.

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

person bers    schedule 26.08.2019

Другой подход: взломать sys.argv, проверить его на --help и -h, если он найден, извлечь текст справки, используя argparse.format_help, помассировать его, распечатать и выйти.

import  sys, re, argparse 

RGX_MID_WS = re.compile(r'(\S)\s{2,}')

def main(argv):

#   note add_help = False
    parser = argparse.ArgumentParser(description = '%(prog)s: testing help mods', formatter_class= argparse.RawTextHelpFormatter, add_help = False)

    parser.add_argument('bar', nargs='+', help='two bars that need to be frobbled')
    parser.add_argument('--foo', action='store_true', help='foo the bars before frobbling\nfoo the bars before frobbling')
    parser.add_argument('--xxxxx', nargs=2, help='many xes')
    parser.add_argument('--bacon', help ='a striped food')
    parser.add_argument('--badger', help='in a striped pyjamas')
    parser.add_argument('--animal', dest='animal', choices=('zabra', 'donkey', 'bat') ,help ='could be one of these')

#   may exit
    lArgs = help_manage(parser)
    args = parser.parse_args() # args = lArgs

    print('bars are: ', args.bar)


def help_manage(parser):
    """
    check for -h, --help, -h in a single-letter cluster;
    if none found, return, otherwise clean up help text and exit
    """

    lArgs = sys.argv[1:]
    lArgsNoHelp = [sOpt for sOpt in lArgs if (not sOpt in ('--help', '-h')) and not (sOpt[0] == '-' and sOpt[1] != '-' and 'h' in sOpt)]

#   no change?  then no --help params
    if len(lArgsNoHelp) == len(lArgs): return

    sHelp = parser.format_help()

#   to see help as formated by argparse, uncomment: 
#   print(sHelp)
#   exit() 

    for sLine in sHelp.split('\n'): print(clean_line(sLine))

    exit() 

def clean_line(sLine):
    """
    this is just an example, and goes nowhere near covering all possible
    argument properties
    """
#   avoid messing with usage: lines
    if 'usage' in sLine: return sLine
    if sLine.startswith('  ') and '[' in sLine: return sLine

    if sLine.endswith(' arguments:'): return sLine + '\n'

    sLine = sLine.lstrip()

    sLine = RGX_MID_WS.sub(r'\1\n', sLine)
    if sLine.startswith('-'): sLine = '\n' + sLine
    return sLine.replace('{', '\n(can be: ').replace('}', ')').replace('\n\n', '\n')

if __name__ == '__main__':

    bRes =  main(sys.argv[1:])
    sys.exit(bRes)

Помогите без форматирования:

usage: argparse_fix_min2.py [--foo] [--xxxxx XXXXX XXXXX] [--bacon BACON]
                                [--badger BADGER] [--animal {zabra,donkey,bat}]
                                bar [bar ...]

    argparse_fix_min2.py: testing help mods

    positional arguments:
      bar                   two bars that need to be frobbled

    optional arguments:
      --foo                 foo the bars before frobbling
                            foo the bars before frobbling
      --xxxxx XXXXX XXXXX   many xes
      --bacon BACON         a striped food
      --badger BADGER       in a striped pyjamas
      --animal {zabra,donkey,bat}
                            could be one of these

с форматированием:

usage: argparse_fix_min2.py [--foo] [--xxxxx XXXXX XXXXX] [--bacon BACON]
                                [--badger BADGER] [--animal {zabra,donkey,bat}]
                                bar [bar ...]

    argparse_fix_min2.py: testing help mods

    positional arguments:

    bar
    two bars that need to be frobbled

    optional arguments:


    --foo
    foo the bars before frobbling
    foo the bars before frobbling

    --xxxxx XXXXX XXXXX
    many xes

    --bacon BACON
    a striped food

    --badger BADGER
    in a striped pyjamas

    --animal 
    (can be: zabra,donkey,bat)
    could be one of these

    """

person EntropyReduction    schedule 19.02.2020

Если вы предоставляете персонализированный formatter_class своему ArgumentParser

parser = argparse.ArgumentParser(formatter_class=help_formatter)

а затем использовать подпарсеры, средство форматирования будет применяться только к справочному сообщению верхнего уровня. Чтобы использовать один и тот же (или какой-то другой) форматер для всех подпарсеров, вам нужно предоставить аргумент formatter_class для каждого вызова add_parser:

subparsers = parser.add_subparsers(metavar="ACTION", dest="action")
child_parser = subparsers.add_parser(
    action_name, formatter_class=help_formatter
)
person taras    schedule 22.11.2020