Python argparse - добавить аргумент в несколько подпарсеров - PullRequest
55 голосов
/ 21 сентября 2011

Мой скрипт определяет один основной парсер и несколько подпарсеров. Я хочу применить аргумент -p к некоторым подпарсерам. Пока код выглядит так:

parser = argparse.ArgumentParser(prog="myProg")
subparsers = parser.add_subparsers(title="actions")

parser.add_argument("-v", "--verbose",
                    action="store_true",
                    dest="VERBOSE",
                    help="run in verbose mode")

parser_create = subparsers.add_parser ("create", 
                                        help = "create the orbix environment")
parser_create.add_argument ("-p", 
                            type = int, 
                            required = True, 
                            help = "set db parameter")

# Update
parser_update = subparsers.add_parser ("update", 
                                        help = "update the orbix environment")
parser_update.add_argument ("-p", 
                            type = int, 
                            required = True, 
                            help = "set db parameter")

Как видите, add_arument ("-p") повторяется дважды. У меня на самом деле гораздо больше подпарсеров. Есть ли способ перебрать существующие подпапки, чтобы избежать повторения?

Для записи я использую Python 2.7

Ответы [ 4 ]

71 голосов
/ 21 сентября 2011

Это может быть достигнуто путем определения родительского парсера , содержащего общие опции:

import argparse

parent_parser = argparse.ArgumentParser(description="The parent parser")
parent_parser.add_argument("-p", type=int, required=True,
                           help="set db parameter")
subparsers = parent_parser.add_subparsers(title="actions")
parser_create = subparsers.add_parser("create", parents=[parent_parser],
                                      add_help=False,
                                      description="The create parser",
                                      help="create the orbix environment")
parser_create.add_argument("--name", help="name of the environment")
parser_update = subparsers.add_parser("update", parents=[parent_parser],
                                      add_help=False,
                                      description="The update parser",
                                      help="update the orbix environment")

Это создает справочные сообщения в формате:

parent_parser.print_help()

Вывод:

usage: main.py [-h] -p P {create,update} ...
The parent parser
optional arguments:
  -h, --help       show this help message and exit
  -p P             set db parameter
actions:
  {create,update}
    create         create the orbix environment
    update         update the orbix environment
parser_create.print_help()

Вывод:

usage: main.py create [-h] -p P [--name NAME] {create,update} ...
The create parser
optional arguments:
  -h, --help       show this help message and exit
  -p P             set db parameter
  --name NAME      name of the environment
actions:
  {create,update}
    create         create the orbix environment
    update         update the orbix environment

Однако, если вы запустите свою программу, вы не столкнетесь с ошибкой, если не укажете действие (т.е.create или update).Если вам нужно такое поведение, измените код следующим образом.

<...>
subparsers = parent_parser.add_subparsers(title="actions")
subparsers.required = True
subparsers.dest = 'command'
<...>

Это исправление было поднято в этом SO-вопросе , который относится к проблеме, отслеживающей запрос на извлечение.

7 голосов
/ 26 августа 2015

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

parser = argparse.ArgumentParser(prog="myProg")
subparsers = parser.add_subparsers(title="actions")
parser.add_argument("-v", "--verbose",
                    action="store_true",
                    dest="VERBOSE",
                    help="run in verbose mode")

parser_create = subparsers.add_parser ("create", 
                                        help = "create the orbix environment")
parser_update = subparsers.add_parser ("update", 
                                        help = "update the orbix environment")

for subparser in [parser_create, parser_update]:
    subparser.add_argument ("-p", 
                            type = int, 
                            required = True, 
                            help = "set db parameter")
4 голосов
/ 12 октября 2017

Вы можете зациклить свои подпарсеры следующим образом.

for name, subp in subparsers.choices.items():
    print(subp)
    subp.add_argument(dest='g', help='Input for g variable', default=7, type=int)

Обратите внимание, что при использовании subparsers.choices вам не нужно жестко кодировать все подпарасеры.

1 голос
/ 14 июня 2019

Принятый ответ правильный, правильный способ - использовать родительские парсеры , однако пример кода IMO на самом деле не решил проблему, позвольте мне добавить несколько моих центов, чтобы предоставить более подходящий пример.

Основным отличием от принятого ответа является явная возможность иметь некоторые аргументы корневого уровня (--verbose), а также общие аргументы только для некоторых подпарасеров (-p только для create и update подпарсер, но не для других)

# Same main parser as usual
parser = argparse.ArgumentParser()

# Usual arguments which are applicable for the whole script / top-level args
parser.add_argument('--verbose', help='Common top-level parameter', action='store_true', required=False)

# Same subparsers as usual
subparsers = parser.add_subparsers(help='Desired action to perform', dest='action')

# Usual subparsers not using common options
parser_other = subparsers.add_parser("extra-action", help='Do something without db')

# Create parent subparser. Note `add_help=False` and creation via `argparse.`
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('-p', help='add db parameter', required=True)

# Subparsers based on parent

parser_create = subparsers.add_parser("create", parents=[parent_parser], help='Create something')
# Add some arguments exclusively for parser_create

parser_update = subparsers.add_parser("update", parents=[parent_parser], help='Update something')
# Add some arguments exclusively for parser_update 

Справочное сообщение верхнего уровня (обратите внимание, что параметр -p здесь не показан, что именно то, что вы ожидаете - потому что он специфичен для некоторых подпарсеров)

>>> parser.print_help()
usage: [-h] [--verbose] {extra-action,create,update} ...

positional arguments:
  {extra-action,create,update}
                        Desired action to perform
    extra-action        Do something without db
    create              Create something
    update              Update something

optional arguments:
  -h, --help            show this help message and exit
  --verbose             Common top-level parameter

И помощь для create действия:

>>> parser_create.print_help()
usage:  create [-h] -p P

optional arguments:
  -h, --help  show this help message and exit
  -p P        add db parameter
...