Как закодировать комбинационные параметры argparse в python
Меня беспокоит эта небольшая часть деятельности, которая должна быть завершена. Я сделал некоторый эксперимент, но не смог добиться результата.
Требование:
test2.py [-c/-v] -f
Использование или правила:
-
-c (compare) принимает 2 параметра.
-v (проверка) принимает 1 параметр.
Любой из этих двух должен присутствовать, но не тот и другой.
- -f - обязательный параметр (имя выходного файла).
Выход:
Я могу получить желаемый результат, как показано ниже
[email protected]:~/Study/scripts$ ./test.py -c P1 P2 -f p
[email protected]:~/Study/scripts$ ./test.py -v P1 -f p
[email protected]:~/Study/scripts$ ./test.py -v P1
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
[email protected]:~/Study/scripts$ ./test.py -c P1 P2
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
[email protected]:~/Study/scripts$
Проблема:
Когда вы используете, test.py -h
,
1. Вывод не укажет, что -c/-v является обязательным, но не оба. Он указывает, что все аргументы являются необязательными.
2. На выходе будет указан параметр -f по необязательным аргументам, который является неправильным. -f является обязательным аргументом, и я хочу отображать внешние аргументы.
Как изменить script так, чтобы выход параметра -h был более удобным (без какой-либо внешней проверки)
usage: test.py <functional argument> <ouput target argument>
Package Compare/Verifier tool.
optional arguments:
-h, --help show this help message and exit
-f outFileName, --file outFileName
File Name where result is stored.
-c Package1 Package2, --compare Package1 Package2
Compare two packages.
-v Package, --verify Package
Verify Content of package.
[email protected]:~/Study/scripts$
Код:
Я использую приведенный ниже код для достижения результата,
#!/usr/bin/python
import sys
import argparse
def main():
usage='%(prog)s <functional argument> <ouput target argument>'
description='Package Compare/Verifier tool.'
parser = argparse.ArgumentParser(usage=usage,description=description)
parser.add_argument('-f','--file',action='store',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')
args = parser.parse_args()
if __name__ == "__main__":
main()
Ответы
Ответ 1
Какой точный результат вы ищете? Я не знаю какого-либо стандартного синтаксиса для обозначения взаимной исключительности в выводе -help, и это, вероятно, будет путать для ваших пользователей, если вы сделаете это. Также я предполагаю, что argparse не поддерживает синтаксис для него (поскольку, если бы это произошло, оно уже работало).
Я предлагаю вам сохранить его простым и просто объяснить своим пользователям взаимное исключение в помощи для каждого из аргументов. Поэтому измените их строки справки следующим образом:
-c Package1 Package2, --compare Package1 Package2
Compare two packages (may not be used with -v).
-v Package, --verify Package
Verify Content of package (may not be used with -c).
Это чрезвычайно очевидно и достаточно кратким.
Другой альтернативой было бы просто не упоминать об этом, и пользователь должен убедиться, что они являются взаимоисключающими, пытаясь использовать их одновременно (argparse автоматически генерирует удобную для пользователя ошибку, такую как "PROG: error: argument -c: not allowed with argument -v
" ).
Ответ 2
Задайте имя файла как позиционный аргумент и argparse
установите собственное сообщение об использовании:
$ python so.py --help
usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName
Имя файла должно быть позиционным, и вы должны позволить argparse
написать собственное сообщение об использовании.
Код
#!/usr/bin/python
import sys
import argparse
def main():
description='Package Compare/Verifier tool.'
parser = argparse.ArgumentParser(description=description,
epilog='--compare and --verify are mutually exclusive')
parser.add_argument('f',action='store',nargs=1,
help='File Name where result is stored.',
metavar="outFileName")
group = parser.add_mutually_exclusive_group(required=False)
group.add_argument('-c','--compare',action='store',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
group.add_argument('-v','--verify',action='store',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')
args = parser.parse_args()
if __name__ == "__main__":
main()
Сообщение справки
$ python so.py --help
usage: so.py [-h] [-c Package1 Package2 | -v Package] outFileName
Package Compare/Verifier tool.
positional arguments:
outFileName File Name where result is stored.
optional arguments:
-h, --help show this help message and exit
-c Package1 Package2, --compare Package1 Package2
Compare two packages.
-v Package, --verify Package
Verify Content of package.
--compare and --verify are mutually exclusive
Ответ 3
Я думаю, что основная жалоба связана с именами групп positional arguments
и optional arguements
по умолчанию. В help
, optional arguments
означает: requires a flag like -f or --file
; positional arguments
означает it is identified by position
. По умолчанию значения positionals
действительно необходимы, а optionals
действительно являются необязательными (не обязательно). Но пользователь может изменить это с помощью атрибута required
, что порождает запутанную терминологию.
Способ определения ваших собственных групп аргументов. Эти группы влияют на расположение help
, но не влияют на разбор. Они также не влияют на строку usage
.
def main():
description='Package Compare/Verifier tool.'
parser = argparse.ArgumentParser(usage=None,description=description)
maingroup = parser.add_argument_group(title='required')
maingroup.add_argument('-f','--file',nargs=1,dest='outFileName',help='File Name where result is stored.',metavar="outFileName",required=True)
exgroup = parser.add_argument_group(title='one or the other')
group = exgroup.add_mutually_exclusive_group(required=True)
group.add_argument('-c','--compare',nargs=2,dest='packageInfo',help='Compare two packages.',metavar=("Package1","Package2"))
group.add_argument('-v','--verify',nargs=1,dest='packageName',help='Verify Content of package.',metavar='Package')
args = parser.parse_args()
дает:
usage: stack5603364.py [-h] -f outFileName (-c Package1 Package2 | -v Package)
Package Compare/Verifier tool.
optional arguments:
-h, --help show this help message and exit
required:
-f outFileName, --file outFileName
File Name where result is stored.
one or the other:
-c Package1 Package2, --compare Package1 Package2
Compare two packages.
-v Package, --verify Package
Verify Content of package.
mutually_exclusive_group
влияет только на строку usage
.
(-c Package1 Package2 | -v Package)
отображает группу, в которой требуется один из вариантов.
[-c Package1 Package2 | -v Package]
будет необязательной группой. []
используются для обозначения необязательных (в аргументе "не обязательно" ). Обратите внимание, как -h
продолжает помечать.
http://bugs.python.org/issue9694 - связанная проблема Python, где автор argparse
поддерживает этот подход argument_group
.