Как закодировать комбинационные параметры 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.