Как я могу заставить Python Argparse перечислять варианты только один раз?

У меня есть код, который выглядит так:

list_of_choices = ["foo", "bar", "baz"]
parser = argparse.ArgumentParser(description='some description')
parser.add_argument("-n","--name","-o","--othername",dest=name,
    choices=list_of_choices

и то, что я получаю на выходе, выглядит так:

-n {foo,bar,baz}, --name {foo,bar,baz}, -o {foo,bar,baz}, 
--othername {foo,bar,baz}

Я бы хотел:

-n, --name, -o, --othername {foo,bar,baz}

Для контекста: есть исторические причины, по которым нам нужны два имени для одной и той же опции, а фактический список вариантов состоит из 22 элементов, поэтому он выглядит намного хуже, чем приведенный выше.

Эта проблема немного отличается от Python argparse: множество вариантов приводит к уродливому выводу справки в том смысле, что я не работаю с двумя отдельными параметрами, и это нормально, чтобы все это было в строке, как указано выше.


person coyot    schedule 20.11.2012    source источник


Ответы (3)


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

list_of_choices = ["foo", "bar", "baz"]
parser = argparse.ArgumentParser(description='some description')
parser.add_argument("-n")
parser.add_argument("--name")
parser.add_argument("-o")
parser.add_argument("--othername", dest='name',
    choices=list_of_choices)
person Thomas Schultz    schedule 20.11.2012
comment
Я не думаю, что это вполне работает, поскольку, если я передам -f foo, позже я получу сообщение об ошибке, говорящее, что name is None. - person coyot; 20.11.2012
comment
Вы пытаетесь уловить все аргументы или просто принимаете те, которые определяете? В этом случае вам придется сделать еще один add_argument() для -f. Также я думаю, что dest должен быть строкой dest='name'. docs.python.org/dev/library/argparse.html#dest - person Thomas Schultz; 20.11.2012

Спасибо, @thomas-schultz. Я не знал о последовательном аспекте add_argument, и ваш комментарий в сочетании с комментарием из другой ветки направил меня на правильный путь.

По сути, сейчас я помещаю все четыре в группу мьютекса, подавляю вывод первых трех и затем включаю их в описание группы.

Вывод выглядит так:

group1
   use one of -n, --name, -o, --othername
-n {foo,bar,baz}

который НАМНОГО чище, чем оригинал.

person coyot    schedule 20.11.2012
comment
Можете ли вы опубликовать код, который у вас есть, чтобы я понял, что вы делаете? :) - person Thomas Schultz; 20.11.2012

Вот код, на котором я остановился после небольшой настройки:

parser = argparse.ArgumentParser(description='some description', 
    epilog="At least one of -n, -o, --name, or --othername is required"
           " and they all do the same thing.") 
parser.add_argument('-d', '--dummy', dest='dummy',
    default=None, help='some other flag')
stuff = parser.add_mutually_exclusive_group(required=True)
stuff.add_argument('-n', dest='name', 
    action='store', choices=all_grids, help=argparse.SUPPRESS)
stuff.add_argument('-o', dest='name', 
    action='store', choices=all_grids, help=argparse.SUPPRESS)
stuff.add_argument('--name', dest='name', 
    action='store', choices=all_grids, help=argparse.SUPPRESS)
stuff.add_argument('--othername', dest='name', 
    action='store', choices=all_grids, help='')
args = parser.parse_args()

вывод с -h - это использование, затем список опций, затем это:

--othername {foo,bar,baz}

At least one of -n, -o, --name, or --othername is required and they all do the same thing.
person coyot    schedule 20.11.2012
comment
Почему бы не отредактировать это в другом ответе? В конце концов, это часть того же ответа. - person Michael; 21.12.2016
comment
Кроме того, action='store' является значением по умолчанию и может быть опущено. - person Michael; 22.01.2020