python,argparse:在指定另一个输入参数时启用输入参数

python,argparse:在指定另一个输入参数时启用输入参数,python,parameters,arguments,argparse,Python,Parameters,Arguments,Argparse,在我的python脚本中,我希望仅当指定了另一个可选参数时才能使用可选输入参数。例如: $ python myScript.py --parameter1 value1 $ python myScript.py --parameter1 value1 --parameter2 value2 但不是: $ python myScript.py --parameter2 value2 如何使用argparse实现这一点 谢谢 使用自定义操作: import argparse foo_defau

在我的python脚本中,我希望仅当指定了另一个可选参数时才能使用可选输入参数。例如:

$ python myScript.py --parameter1 value1
$ python myScript.py --parameter1 value1 --parameter2 value2
但不是:

$ python myScript.py --parameter2 value2
如何使用argparse实现这一点

谢谢

使用自定义操作:

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())
在本例中,我们从
add_argument
返回的action对象中获取
foo
的默认值及其目的地(add_argument的返回值在我能找到的任何地方都没有文档记录)。这仍然有点脆弱(例如,如果要为
--foo
参数指定
type=
关键字)

最后,您可以在解析之前检查
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
)。与前面一样,您可以通过
解析器返回的
选项\u strings
属性获取将触发特定操作的命令字符串列表。添加参数(…)
。e、 g

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))

一种方法是手动检查调用
parser.parse_args()
的输出,如果使用了
--parameter2
,但没有使用
--parameter1
,则会引发异常或失败

您还可以尝试将a(向下滚动一点)设置为
--parameter2
检查命名空间中是否存在
--parameter1

最后,您可以尝试使用,尽管我不知道它是否允许您为
--parameter1

指定一个值,您可以使用该值在将
--parameter2
添加到解析器之前检查
--parameter1
是否已给出

import argparse
parser=argparse.ArgumentParser()
parser.add_参数('--parameter1',dest='p1')
args=parser.parse_known_args()[0]
如果args.p1:
parser.add_参数('--parameter2',dest='p2')
args=parser.parse_args()
如果args.p1:
打印args.p1
如果args.p2:
打印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

如果
myScript.py--parameter2值2--parameter1值1
,您希望发生什么?如果你想让它通过,这是一个很难处理的案件。是对
相互包含的组
功能的错误请求。在这种情况下,这不太管用,因为
--parameter1
可以在没有
--parameter2
的情况下出现。如果您对如何实现此约束或相关约束有想法,请对此问题做出贡献。
--help
将是不准确的。