Ric*_*son 12 python parameters arguments argparse
在我的python脚本中,我希望只有在指定了另一个可选参数时才能使用可选的输入参数.例:
$ python myScript.py --parameter1 value1
$ python myScript.py --parameter1 value1 --parameter2 value2
Run Code Online (Sandbox Code Playgroud)
但不是:
$ python myScript.py --parameter2 value2
Run Code Online (Sandbox Code Playgroud)
我如何使用argparse做到这一点?
谢谢!
mgi*_*son 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())
Run Code Online (Sandbox Code Playgroud)
如果您依赖于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())
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我们foo从返回的action对象中获取默认值和它的目标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")
Run Code Online (Sandbox Code Playgroud)
如果--parameter1也可以触发--p1,这会变得有点棘手,但你明白了.然后你可以使用
if (set(sys.argv).intersection(('--p2',...)) and
not set(sys.argv).intersection(('--p1',...)))
Run Code Online (Sandbox Code Playgroud)
这里的优点是它不需要任何特定的顺序.(--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))
Run Code Online (Sandbox Code Playgroud)