2016-10-19 8 views
0

Мне интересно, как я могу сделать один аргумент, требуемый при задании одного флага, и необязательный, если этот флаг не указан?Python Argparse: как сделать аргумент требуемым тогда и только тогда, когда задан один флаг?

import argparse 


parser = argparse.ArgumentParser() 

parser.add_argument('-c', '--convert', action = 'store_true') 
parser.add_argument('-l', '--lookup', action = 'store_true') 
parser.add_argument('name', type = str) 

args = parser.parse_args() 

if args.name: 
    print(args.name) 
if args.convert: 
    print ("convert now!") 

Например, в приведенных выше кодов, я хочу name быть необходимы только тогда, когда -c дается. Когда я запускаю программу только с -l, то есть ошибка:

$ python3 test.py -l 
usage: test.py [-h] [-c] [-l] name 
test.py: error: the following arguments are required: name 

Я попытался использовать аргумент группы разделить аргументы на две группы 1. -c и name; 2. -l, но это действительно не сработало.

Любые предложения приветствуются!

ответ

1

Для этого не нужно ничего в argparse; но она может быть аппроксимирована различными способами

parser.add_argument('-c', '--convert', action = 'store_true') 
parser.add_argument('-l', '--lookup', action = 'store_true') 
parser.add_argument('name', nargs='?', default='good default') 

Это не обязательно в любом случае, но в случае -c вы можете использовать либо good default, или вы можете подать жалобу после разбора.

parser.add_argument('-c', '--convert') 
parser.add_argument('-l', '--lookup', nargs='?', default='adefault', const='aconst') 

В этом случае -c ожидает аргумент, ваше необходимое name. Аргумент необязателен для -l. Если нет -l, значение равно default; если -l без аргумента, значение равно const. Вы можете даже поставить -c и -l во взаимовыгодную группу.

Существует не механизм, требующий объединения нескольких аргументов (т. Е. Нет взаимно обязательной группы). Однако подэлементы работают по этой линии. Нужно ли мне проиллюстрировать, как можно использовать субпараметры здесь?

Классы пользовательских действий могут использоваться для принудительного взаимодействия между аргументами, но обычно проще выполнять такие вещи после разбора. Помните, что argparse позволяет давать аргументы в любом порядке. Таким образом, позиционирование name могло произойти до -c или после или между -l и -c и т. Д.

+0

Спасибо за подробное объяснение, это очень помогает! Я могу учиться у субпараторов самостоятельно :) –

2

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

import argparse 


parser = argparse.ArgumentParser() 

parser.add_argument('-c', '--convert', action='store_true') 
parser.add_argument('-l', '--lookup', action='store_true') 
parser.add_argument('name', nargs='?') 

args = parser.parse_args() 

# If args.name must be a non-empty string when given, 
# you can use 'not args.name' in place of 'args.name is None' 
if args.convert and args.name is None: 
    parser.error("<name> required with --convert") 

if args.name: 
    print(args.name) 
if args.convert: 
    print ("convert now!") 
+0

Спасибо, получилось сейчас. Разумно использовать 'parser.error' здесь! –