2013-11-18 3 views
7

Предположим, что у меня есть скрипт argparse Python:argparse вариант по умолчанию на основе другого варианта

import argparse 
parser = argparse.ArgumentParser() 

parser.add_argument("--foo", required=True) 

Теперь я хочу добавить еще один вариант --bar, который будет по умолчанию для добавления «_BAR» к тому, что было указано - -foo.

Моя цель:

>>> parser.parse_args(['--foo', 'FOO']) 
>>> Namespace(foo='FOO', bar="FOO_BAR") 

И

>>> parser.parse_args(['--foo', 'FOO', '--bar', 'BAR']) 
>>> Namespace(foo='FOO', bar="BAR") 

мне нужно что-то вроде этого:

parser.add_argument("--bar", default=get_optional_foo + "_BAR") 

ответ

3

Вот еще одна попытка написать пользовательский класс Экшены

import argparse 
class FooAction(argparse.Action): 
    # adapted from documentation 
    def __call__(self, parser, namespace, values, option_string=None): 
     setattr(namespace, self.dest, values) 
     defaultbar = getattr(namespace, 'bar') 
     try: 
      defaultbar = defaultbar%values 
     except TypeError: 
      # BAR has already been replaced 
      pass 
     setattr(namespace, 'bar', defaultbar) 

parser = argparse.ArgumentParser() 
parser.add_argument("--foo", required=True, action=FooAction) 
parser.add_argument("--bar", default="%s_BAR") 

args = parser.parse_args(['--foo', 'Foo', '--bar', 'Bar']) 
# Namespace(bar='Bar', foo='Foo') 
args = parser.parse_args(['--foo', 'Foo']) 
# Namespace(bar='Foo_BAR', foo='Foo') 
args = parser.parse_args(['--bar', 'Bar', '--foo', 'Foo']) 
# Namespace(bar='Bar', foo='Foo') 

Обратите внимание, что класс должен знать dest из --bar аргумента. Кроме того, я использую '%s_BAR', чтобы легко различать значение по умолчанию и значение по умолчанию. Это обрабатывает случай, когда --bar появляется перед --foo.

вещи, которые усложняют этот подход является:

  • значения по умолчанию вычисляется в add_argument время.
  • значения по умолчанию помещаются в пространство имен в начале parse_args.
  • аргументы с флагом (необязательные) могут иметь место в любом порядке
  • класс Action не предназначен для обработки взаимодействующих аргументов.
  • Операция bar не будет вызываться в случае по умолчанию.
  • bar по умолчанию может быть функцией, но что-то должно было бы после parse_args проверить, нужно ли это оценивать или нет.

Хотя это обычное действие делает трюк, я все еще думаю, что функция addbar в моем другом ответе - это более чистое решение.

4

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

def addbar(args): 
    if args.bar is None: 
     args.bar = args.foo+'_BAR' 

Если это действие должно быть отражено в help, положил его туда сам.

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

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

+0

Хотелось бы знать, почему это было проголосовано.Никто другой не предложил решение, а тем более лучшее. – hpaulj

+0

Не знаю, но +1 от меня. Мне нравится простота этого решения лучше, чем пользовательское действие, хотя подкласс ArgumentParser, добавляющий зависимости между аргументами, будет довольно круто. – sfink

Смежные вопросы