Как кодировать argparse комбинационные опции в python - PullRequest
17 голосов
/ 09 апреля 2011

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

Требование:

   test2.py [-c/-v] -f

Использование или правила:

  1. -c (сравнение) принимает 2 параметра.

    -v (проверка) принимает 1 параметр.

    Должен присутствовать либо из этих двух, , но не оба .

  2. -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()

Ответы [ 3 ]

21 голосов
/ 09 апреля 2011

Установите имя файла в качестве позиционного аргумента, и пусть 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
7 голосов
/ 09 апреля 2011

Какой именно вывод вы ищете?Я не знаю ни одного стандартного синтаксиса для обозначения взаимной исключительности в выводе --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 голосов
/ 22 ноября 2013

Я думаю, что основная жалоба связана с именами групп по умолчанию 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 подход.

...