Вопрос по parameters, python, arguments, argparse – python, argparse: включить входной параметр, если указан другой

12

В моем скрипте Python я хочу использовать дополнительный входной параметрonly когда был указан другой необязательный параметр. Пример:

$ python myScript.py --parameter1 value1
$ python myScript.py --parameter1 value1 --parameter2 value2

Но нет:

$ python myScript.py --parameter2 value2

Как мне сделать это с argparse?

Спасибо!

Что ты хочешь случиться, еслиmyScript.py --parameter2 value2 --parameter1 value1? Это очень сложный случай, если вы хотите, чтобы он прошел. mgilson
bugs.python.org/issue11588 это запрос об ошибке дляmutually_inclusive_group особенность. Это не будет работать в этом случае, так как--parameter1 может произойти без--parameter2, Внесите свой вклад в этот вопрос, если у вас есть идеи о том, как это или связанные ограничения могут быть реализованы. hpaulj

Ваш Ответ

3   ответа
2

parse_known_args () проверить, если--parameter1 было дано перед добавлением--parameter2 парсеру.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--parameter1', dest='p1')
args = parser.parse_known_args()[0]
if args.p1:
  parser.add_argument('--parameter2', dest='p2')
args = parser.parse_args()

if args.p1:
  print args.p1
if args.p2:
  print args.p2

Результаты:

$ python myScript.py --parameter1 a
a
$ python myScript.py --parameter1 a --parameter2 b
a
b
$ python myScript.py --parameter2 b
usage: myScript.py [-h] [--parameter1 P1]
myScript.py: error: unrecognized arguments: --parameter2 b
--help будет неточным, хотя.
10

import argparse

foo_default=None    

class BarAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        didfoo=getattr(namespace,'foo',foo_default)
        if(didfoo == foo_default):
            parser.error( "foo before bar!")
        else:
            setattr(namespace,self.dest,values)

parser=argparse.ArgumentParser()
parser.add_argument('--foo',default=foo_default)
parser.add_argument('--bar',action=BarAction,help="Only use this if --foo is set")

#testing.
print parser.parse_args('--foo baz'.split())
print parser.parse_args('--foo baz --bar cat'.split())
print parser.parse_args('--bar dog'.split())

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

import argparse

parser=argparse.ArgumentParser()
first_action=parser.add_argument('--foo',dest='cat',default=None)

class BarAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        didfoo=getattr(namespace,first_action.dest,first_action.default)
        if(didfoo == first_action.default):
            parser.error( "foo before bar!")
        else:
            setattr(namespace,self.dest,values)

parser.add_argument('--bar',action=BarAction,
                    help="Only use this if --foo is set")

#testing.
print parser.parse_args('--foo baz'.split())
print parser.parse_args('--foo baz --bar cat'.split())
print parser.parse_args('--bar dog'.split())

В этом примере мы получаем значение по умолчанию дляfoo и это место назначения от объекта действия, возвращенногоadd_argument (Возвращаемое значение add_argument не задокументировано где-либо, что я могу найти). Это все еще немного хрупкий (Если вы хотите указатьtype= ключевое слово для--foo аргумент например).

Наконец, вы можете проверитьsys.argv до разбора.

import sys
if ("--parameter2" in sys.argv) and ("--parameter1" not in sys.argv):
    parser.error("parameter1 must be given if parameter2 is given")

Это становится немного сложнее, если--parameter1 также может быть вызвано--p1, Но ты получил идею. Тогда вы могли бы использовать

if (set(sys.argv).intersection(('--p2',...)) and 
    not set(sys.argv).intersection(('--p1',...)))

Преимущество здесь состоит в том, что он не требует какого-либо конкретного заказа. (--p2 не нужно следовать--p1 в командной строке). И, как и прежде, вы можете получить список командных строк, которые будут запускать ваше конкретное действие черезoption_strings атрибут, возвращаемыйparser.add_argument(...), например

import argparse
import sys   
parser=argparse.ArgumentParser()
action1=parser.add_argument('--foo')
action2=parser.add_argument('--bar',
                            help="Only use this if --foo is set")

argv=set(sys.argv)
if (( argv & set(action2.option_strings) ) and 
      not ( argv & set(action1.option_strings) )):
                #^ set intersection
     parser.error(' or '.join(action1.option_strings)+
                  ' must be given with '+
                  ' or '.join(action2.option_strings))
2

parser.parse_args() и поднять исключение или иным образом потерпеть неудачу, если--parameter2 используется но--parameter1 ISN & APOS; т.

Вы также можете попробовать установитьпользовательское действие (прокрутите немного вниз), чтобы--parameter2 проверить, если--parameter1 существует внутри пространства имен.

Наконец, вы можете попробовать использоватьsubparsersхотя я не знаю, позволит ли он вам указать значение для--parameter1.

Похожие вопросы