在我的 python 脚本中,我希望只有在指定了另一个可选参数时才能使用可选输入参数。例子:
$ python myScript.py --parameter1 value1
$ python myScript.py --parameter1 value1 --parameter2 value2
但不是:
$ python myScript.py --parameter2 value2
如何使用 argparse 执行此操作?
谢谢!
在我的 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())
在此示例中,我们从返回的操作对象中获取默认值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))
您可以使用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
一种想法是手动检查调用的输出parser.parse_args()
并引发异常,否则如果--parameter2
使用但未使用则失败--parameter1
。
您还可以尝试设置自定义操作(向下滚动一点)以--parameter2
检查--parameter1
名称空间内是否存在。
最后,您可以尝试使用subparsers,尽管我不知道它是否会让您为--parameter1
.