Argparse: Требуемый аргумент 'y', если присутствует 'x'
У меня есть следующее требование:
./xyifier --prox --lport lport --rport rport
для аргумента prox, я использую action = 'store_true', чтобы проверить, присутствует ли он или нет.
Я не требую никаких аргументов. Но, если --prox установлен, мне также нужны rport и lport. Есть ли простой способ сделать это с помощью argparse без написания условного условного кодирования.
Подробнее Код:
non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', type=int, help='Listen Port.')
non_int.add_argument('--rport', type=int, help='Proxy port.')
Ответы
Ответ 1
Нет, в argparse нет никакой опции для создания взаимоисключающих наборов параметров.
Самый простой способ справиться с этим:
if args.prox and args.lport is None and args.rport is None:
parser.error("--prox requires --lport and --rport.")
Ответ 2
Вы говорите о наличии условно необходимых аргументов. Подобно @borntyping, вы можете проверить наличие ошибки и сделать parser.error()
, или вы можете просто применить требование, связанное с --prox
, когда вы добавляете новый аргумент.
Простым решением для вашего примера может быть:
non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', required='--prox' in sys.argv, type=int)
non_int.add_argument('--rport', required='--prox' in sys.argv, type=int)
Таким образом required
получает либо True
, либо False
в зависимости от того, используется ли пользователь --prox
. Это также гарантирует, что -lport
и -rport
имеют независимое поведение между собой.
Ответ 3
Используете ли вы lport
, когда prox
не установлен. Если нет, почему бы не сделать аргументы lport
и rport
prox
? например.
parser.add_argument('--prox', nargs=2, type=int, help='Prox: listen and proxy ports')
Это экономит ваши пользователи. Так же легко проверить if args.prox is not None:
как if args.prox:
.
Ответ 4
Как насчет использования метода parser.parse_known_args()
, а затем добавьте аргументы --lport
и --rport
в качестве требуемых аргументов, если --prox
присутствует.
# just add --prox arg now
non_int = argparse.ArgumentParser(description="stackoverflow question",
usage="%(prog)s [-h] [--prox --lport port --rport port]")
non_int.add_argument('--prox', action='store_true',
help='Flag to turn on proxy, requires additional args lport and rport')
opts, rem_args = non_int.parse_known_args()
if opts.prox:
non_int.add_argument('--lport', required=True, type=int, help='Listen Port.')
non_int.add_argument('--rport', required=True, type=int, help='Proxy port.')
# use options and namespace from first parsing
non_int.parse_args(rem_args, namespace = opts)
Также имейте в виду, что вы можете предоставить пространство имен opts
, сгенерированное после первого синтаксического анализа, при повторном анализе остальных аргументов. Таким образом, в конце концов, после всего разбора, у вас будет одно пространство имен со всеми параметрами.
Недостатки:
- Если
--prox
нет, другие два зависимых параметра даже не присутствуют в пространстве имен. Хотя на основе вашего прецедента, если --prox
нет, то что происходит с другими параметрами, не имеет значения.
- Необходимо изменить сообщение об использовании, поскольку парсер не знает полную структуру.
-
--lport
и --rport
не отображаются в справочном сообщении