在解析器/子解析器的开头使用 argparse.REMAINDER
Using argparse.REMAINDER at beginning of parser / sub parser
我想实现一个 arg 解析器,允许我将 运行 单元测试作为子命令之一,盲目地将参数传递给 unittest.main()。例如,
$ foo.py unittest [args to pass to unittest.main()]
连同其他子命令:
$ foo.py foo ...
$ foo.py bar ...
按照 argparse 的例子,这个有效:
#!/usr/bin/python
import argparse
p = argparse.ArgumentParser(prog='PROG')
p.add_argument('-v', '--verbose', action='store_true')
sub = p.add_subparsers(dest='cmd')
foo = sub.add_parser('foo')
bar = sub.add_parser('bar')
unittest = sub.add_parser('unittest')
unittest.add_argument('command') # Need to add this to make it work.
unittest.add_argument('args', nargs=argparse.REMAINDER)
print(p.parse_args('unittest command -blah blah'.split()))
输出:
Namespace(args=['-blah', 'blah'], cmd='unittest', command='command', verbose=False)
但这不是。似乎首先需要一个 "normal" 参数:
#!/usr/bin/python
import argparse
p = argparse.ArgumentParser(prog='PROG')
p.add_argument('-v', '--verbose', action='store_true')
sub = p.add_subparsers(dest='cmd')
foo = sub.add_parser('foo')
bar = sub.add_parser('bar')
unittest = sub.add_parser('unittest')
unittest.add_argument('args', nargs=argparse.REMAINDER)
print(p.parse_args('unittest -blah blah'.split()))
输出:
$ /tmp/foo.py
usage: PROG [-h] [-v] {foo,bar,unittest} ...
PROG: error: unrecognized arguments: -blah
我可以做print(p.parse_args('unittest -- -f -g'.split()))
,但是要求--
有点违背argparse.REMAINDER的目的。
有没有办法让 argparse
做我想做的事?还是我只需要手动解析这个案例?
Python 2.7.5
看起来与 http://bugs.python.org/issue17050、argparse.REMAINDER doesn't work as first argument
中讨论的问题相同
我 4 年前的推论仍然成立 - -blah
甚至在 REMAINDER
有机会采取行动之前就被归类为可选标志。 '--' 被较早地解析,但 ...
在某种意义上只是 '*' 的概括。而且不是广泛使用的。对于它的价值,'subparsers' 操作有一个 nargs='+...'
值 (argparse.PARSER
) - 它类似于 REMAINDER,除了它需要至少一个字符串,'cmd'.
http://bugs.python.org/issue9334 中可能的修复尚未执行。所以你要么需要自己处理'-blah',要么使用'--'。 parse_known_args
也可能适用于您的情况。
如前所述,现有行为很糟糕。一种解决方法是实施一个简单的
ArgumentParser
子类化并将其用于您的子解析器:
class SubcommandParser(argparse.ArgumentParser):
"""This subparser puts all remaining arguments in args attribute of namespace"""
def parse_known_args(self, args=None, namespace=None):
if namespace is None:
namespace = argparse.Namespace()
setattr(namespace, 'args', args)
return namespace, []
...
p.add_subparsers(dest='cmd', parser_class=SubcommandParser)
我想实现一个 arg 解析器,允许我将 运行 单元测试作为子命令之一,盲目地将参数传递给 unittest.main()。例如,
$ foo.py unittest [args to pass to unittest.main()]
连同其他子命令:
$ foo.py foo ...
$ foo.py bar ...
按照 argparse 的例子,这个有效:
#!/usr/bin/python
import argparse
p = argparse.ArgumentParser(prog='PROG')
p.add_argument('-v', '--verbose', action='store_true')
sub = p.add_subparsers(dest='cmd')
foo = sub.add_parser('foo')
bar = sub.add_parser('bar')
unittest = sub.add_parser('unittest')
unittest.add_argument('command') # Need to add this to make it work.
unittest.add_argument('args', nargs=argparse.REMAINDER)
print(p.parse_args('unittest command -blah blah'.split()))
输出:
Namespace(args=['-blah', 'blah'], cmd='unittest', command='command', verbose=False)
但这不是。似乎首先需要一个 "normal" 参数:
#!/usr/bin/python
import argparse
p = argparse.ArgumentParser(prog='PROG')
p.add_argument('-v', '--verbose', action='store_true')
sub = p.add_subparsers(dest='cmd')
foo = sub.add_parser('foo')
bar = sub.add_parser('bar')
unittest = sub.add_parser('unittest')
unittest.add_argument('args', nargs=argparse.REMAINDER)
print(p.parse_args('unittest -blah blah'.split()))
输出:
$ /tmp/foo.py
usage: PROG [-h] [-v] {foo,bar,unittest} ...
PROG: error: unrecognized arguments: -blah
我可以做print(p.parse_args('unittest -- -f -g'.split()))
,但是要求--
有点违背argparse.REMAINDER的目的。
有没有办法让 argparse
做我想做的事?还是我只需要手动解析这个案例?
Python 2.7.5
看起来与 http://bugs.python.org/issue17050、argparse.REMAINDER doesn't work as first argument
我 4 年前的推论仍然成立 - -blah
甚至在 REMAINDER
有机会采取行动之前就被归类为可选标志。 '--' 被较早地解析,但 ...
在某种意义上只是 '*' 的概括。而且不是广泛使用的。对于它的价值,'subparsers' 操作有一个 nargs='+...'
值 (argparse.PARSER
) - 它类似于 REMAINDER,除了它需要至少一个字符串,'cmd'.
http://bugs.python.org/issue9334 中可能的修复尚未执行。所以你要么需要自己处理'-blah',要么使用'--'。 parse_known_args
也可能适用于您的情况。
如前所述,现有行为很糟糕。一种解决方法是实施一个简单的
ArgumentParser
子类化并将其用于您的子解析器:
class SubcommandParser(argparse.ArgumentParser):
"""This subparser puts all remaining arguments in args attribute of namespace"""
def parse_known_args(self, args=None, namespace=None):
if namespace is None:
namespace = argparse.Namespace()
setattr(namespace, 'args', args)
return namespace, []
...
p.add_subparsers(dest='cmd', parser_class=SubcommandParser)