Условные требования Python argparse

Как настроить argparse следующим образом:

if -2 is on the command line, no other arguments are required
if -2 is not on the command line, -3 and -4 arguments are required

Например,

-2 [good]
-3 a -4 b [good]
-3 a [not good, -4 required]
-2 -5 c [good]
-2 -3 a [good]

Здесь есть ряд подобных вопросов, но либо они не затрагивают эту ситуацию, либо я не понимаю.

Python 2.7, если это имеет значение.

Ответ 1

Подпараметр (как это предлагается в комментариях) может работать.

Другая альтернатива (так как mutually_exclusive_group не может это сделать) заключается в том, чтобы просто ее закодировать вручную:

import argparse

def main():
    parser = argparse.ArgumentParser()

    parser.add_argument('-2', dest='two', action='store_true')
    parser.add_argument('-3', dest='three')
    parser.add_argument('-4', dest='four')
    parser.add_argument('-5', dest='five')

    args = parser.parse_args()

    if not args.two:
        if args.three is None or args.four is None:
            parser.error('without -2, *both* -3 <a> *and* -4 <b> are required')

    print args
    return 0

Добавление небольшого драйвера к этому:

import sys
sys.exit(main())

и работать с вашими примерами, он, кажется, поступает правильно; вот два прогона:

$ python mxgroup.py -2; echo $?
Namespace(five=None, four=None, three=None, two=True)
0
$ python mxgroup.py -3 a; echo $?
usage: mxgroup.py [-h] [-2] [-3 THREE] [-4 FOUR] [-5 FIVE]
mxgroup.py: error: without -2, *both* -3 <a> *and* -4 <b> are required
2
$ 

Ответ 2

Я думаю, что это довольно сложно достичь (включая хорошее справочное сообщение), но только с использованием стандартных функций argparse. Однако вы можете легко протестировать его после разбора аргументов. Вы можете описать дополнительные требования в эпилоге или около того. Обратите внимание, что необычно использовать числа в качестве параметров, мне пришлось использовать dest = 'two', так как args.2 не является допустимым синтаксисом.

#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser(
   description='bla bla',
   epilog='Note: arguments -3 and -4 are required when -2 is missing')

parser.add_argument('-2', dest='two', action='store_true')
parser.add_argument('-3', dest='three')
parser.add_argument('-4', dest='four')
parser.add_argument('-5', dest='five')

args = parser.parse_args()

if not args.two and (args.three is None or args.four is None):
    parser.error('arguments -3 and -4 are required when -2 is missing')

print 'Good:', args

С этими результатами:

[~]: ./test.py -h
usage: test.py [-h] [-2] [-3 THREE] [-4 FOUR] [-5 FIVE]

bla bla

optional arguments:
  -h, --help  show this help message and exit
  -2
  -3 THREE
  -4 FOUR
  -5 FIVE

Note: arguments -3 and -4 are required when -2 is missing

[~]: ./test.py -2
Good: Namespace(five=None, four=None, three=None, two=True)
[~]: ./test.py -3 a -4 b
Good: Namespace(five=None, four='b', three='a', two=False)
[~]: ./test.py -3 a
usage: test.py [-h] [-2] [-3 THREE] [-4 FOUR] [-5 FIVE]
test.py: error: arguments -3 and -4 are required when -2 is missing
[~]: ./test.py -2 -5 c
Good: Namespace(five='c', four=None, three=None, two=True)
[~]: ./test.py -2 -3 a
Good: Namespace(five=None, four=None, three='a', two=True)