一个不需要位置参数的可选参数
我有个关于Python的argparse库的问题:有没有办法让一个可选参数不需要位置参数?
举个例子:
parser.add_argument('lat', help="latitude")
parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")
parser.add_argument('--list-methods', help="list available methods", action="store_true")
正常情况下,命令行的输入会是 test.py 47.249 -33.282
或者 test.py 47.249 -33.282 --method sub
。但是当我用 test.py --list-methods
来列出所有可用的方法时,就会出现 error: to few arguments
的错误。这种情况下,我该怎么用argparse来实现这个可选参数(--list-methods),而不需要位置参数(纬度和经度)呢?
3 个回答
你看到 error: to few arguments
这个错误,是因为程序需要你提供 lat
和 lon
这两个参数。
In [10]: parser.parse_args('--list-methods'.split())
ipython: error: too few arguments
但是
In [11]: parser.parse_args('--list-methods 10 20'.split())
Out[11]: Namespace(lat='10', list_methods=True, lon='20', method='add')
你应该把 lat
和 lon
这两个参数设置成可选的。
从Python 3.3开始,parse_args
会检查它所看到的动作(seen_actions
)是否满足所需的动作,并在需要时给出“以下参数是必需的...”的错误提示。之前,它会检查剩下的必填参数(positionals
),如果不够就会抛出“参数太少”的错误信息。
所以在新版本中,这段代码应该能满足你的需求:
parser = argparse.ArgumentParser()
lat=parser.add_argument('lat', help="latitude")
lon=parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")
class MyAction(argparse._StoreTrueAction):
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, self.const)
lat.required = False
lon.required = False
parser.add_argument('--list-methods', help="list available methods", action=MyAction)
通常情况下,lat
和lon
是必填的参数,但如果执行了--list...
这个动作,那么这些参数就不再是必需的,如果缺少它们也不会出现错误信息。
另外一种自定义argparse的方法是使用多个解析器。在这种情况下,你可以用一个解析器来检查--list-methods
这个选项,然后根据得到的结果去调用另一个解析器来查找必填参数。
parser1 = argparse.ArgumentParser(add_help=False)
parser1.add_argument('--list-methods', help="list available methods", action='store_true')
parser2 = argparse.ArgumentParser()
parser2.add_argument('lat', help="latitude")
parser2.add_argument('lon', help="longitude")
parser2.add_argument('--method', help="calculation method (default: add)", default="add")
parser2.add_argument('--list-methods', help="list available methods", action='store_true')
def foo(argv):
args,rest = parser1.parse_known_args(argv)
if not args.list_methods:
args = parser2.parse_args(argv)
return args
parser2
会响应帮助命令。parse_known_args
会解析它能解析的内容,并把剩下的部分以列表的形式返回。parser2
也可以被写成接受rest, args
作为参数。
- 为你的位置参数设置一个默认值,并且使用
nargs='?'
。 在你的代码中手动检查一下,当你不在 list-methods 模式时,latitude 和 longitude 是否都已经设置好。
parser = argparse.ArgumentParser() parser.add_argument('lat', help="latitude",default=None, nargs='?') parser.add_argument('lon', help="longitude",default=None, nargs='?') parser.add_argument('--method', help="calculation method (default: add)", default="add") parser.add_argument('--list-methods', help="list available methods", action="store_true") args = vars(parser.parse_args()) if not args['list_methods'] and (args['lat'] == None or args['lon'] == None): print '%s: error: too few arguments' % sys.argv[0] exit(0) if args['list_methods']: print 'list methods here' else : print 'normal script execution'
这样会得到:
$ test.py --list-methods
这里列出方法$ test.py 4
test.py: 错误:参数太少test.py 4 5
正常执行脚本