#python #argparse
#python #argparse
Вопрос:
У меня возникли проблемы с этим небольшим этапом работы, который необходимо завершить. Я провел некоторый эксперимент, но не смог добиться результата.
Требование:
test2.py [-c/-v] -f
Использование или правила:
-
-c (compare) принимает 2 параметра.
-v (verify) принимает 1 параметр.
Любой из этих двух должен присутствовать, но не оба.
- -f является обязательным параметром (имя выходного файла).
Вывод:
Я могу получить желаемый результат, как показано ниже
kp@kp:~/Study/scripts$ ./test.py -c P1 P2 -f p
kp@kp:~/Study/scripts$ ./test.py -v P1 -f p
kp@kp:~/Study/scripts$ ./test.py -v P1
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
kp@kp:~/Study/scripts$ ./test.py -c P1 P2
usage: test.py <functional argument> <ouput target argument>
test.py: error: argument -f/--file is required
kp@kp:~/Study/scripts$
Проблема в:
При использовании, test.py -h
,
1. В выходных данных не будет указано, что -c /-v любой из них является обязательным, но не оба . Это указывает на то, что все аргументы являются необязательными.
2. В выходных данных будет указана опция -f в необязательных аргументах, что неверно. -f является обязательным аргументом, и я хочу отобразить внешние необязательные аргументы.
Как изменить скрипт, чтобы вывод опции -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.
kiran@kiran-laptop:~/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. В дополнение к замене
-f
позиционным аргументом, я бы сделалcompare
иverify
две подкоманды, а не пару взаимоисключающих обязательных параметров. (test.py compare P1 P2 output.txt
иtest.py verify P1 output.txt
; обратите внимание, что позиционные аргументы должны быть указаны для каждого подразделителя. В качестве альтернативы, создайте-f
параметр, который по умолчанию использует стандартный вывод; вы можете сохранить параметры в главном анализаторе, чтобы они применялись независимо от того, какая подкоманда задана).
Ответ №1:
Задайте имя файла в качестве позиционного аргумента, и пусть 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
Комментарии:
1. Это было близко, но также технически мне нужно -f из необязательных аргументов в файле справки. Поскольку заголовок «необязательные аргументы:» вводит в заблуждение, когда -f является обязательным аргументом.
2. Обновлен мой ответ, файл теперь является позиционным аргументом.
3. @Matan, Но с измененным кодом — python so.py out.txt работает. Что неверно — поскольку -c /-v (один из них должен присутствовать).
4. если вы установите
required=True
, решит ли это проблему?
Ответ №2:
Какой точный вывод вы ищете? Мне неизвестен какой-либо стандартный синтаксис для обозначения взаимной исключительности в выводе —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
«).
Комментарии:
1. после недельного ожидания не получили правильного ответа, ваш ответ кажется наиболее практичным. похоже, другого технического способа решения нет.
Ответ №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
подход.