Argparse - do not catch positional arguments with `nargs`.
我正在尝试编写一个函数wo,您可以通过argparse解析变量数量的参数-我知道我可以通过
1 2 3 4 5 6 7 8 | #!/usr/bin/python import argparse parser = argparse.ArgumentParser() parser.add_argument("positional", help="my positional arg", type=int) parser.add_argument("-o","--optional", help="my optional arg", nargs='+', type=float) args = parser.parse_args() print args.positional, args.optional |
以
1 | usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] positional |
但是如果我运行
1 | test.py: error: too few arguments |
为了正确解析args,我必须运行
我该怎么办:
使argparse重新格式化使用率输出,以减少误导,甚至更好:
告诉argparse不要捕获可选参数
-o 的最后一个元素(如果它是列表中的最后一个元素)
?
有一个关于这个的bug报告:http://bugs.python.org/issue9338
argparse optionals with nargs='?', '*' or '+' can't be followed by positionals
一个简单的(用户)修复方法是使用
1 | ./test.py -o 0.21 0.11 0.33 0.13 -- 100 |
我写了一个补丁,它保留了一些由位置使用的参数。但这不是一件小事。
至于更改使用行-最简单的方法是自己写,例如:
1 2 | usage: test.py [-h] positional [-o OPTIONAL [OPTIONAL ...]] usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] -- positional |
我不建议向usage格式化程序添加逻辑来进行这种更改。我认为这会变得太复杂。
另一个快速修复方法是将这个位置转换成(必需的)可选的。它为用户提供了关于他们的订单的完全自由,并可能减少混乱。如果您不想混淆"必选"选项,只需给它一个逻辑默认值。
1 2 | usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] -p POSITIONAL usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] [-p POS_WITH_DEFAULT] |
帮助格式化程序的一个简单更改是按照定义的顺序简单地列出参数。修改格式化程序行为的正常方法是对其进行子类化,并更改一两个方法。这些方法中的大多数都是"private"(前缀),因此,您需要认识到未来的代码可能会发生变化(缓慢)。
在这种方法中,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class Formatter(argparse.HelpFormatter): # use defined argument order to display usage def _format_usage(self, usage, actions, groups, prefix): if prefix is None: prefix = 'usage: ' # if usage is specified, use that if usage is not None: usage = usage % dict(prog=self._prog) # if no optionals or positionals are available, usage is just prog elif usage is None and not actions: usage = '%(prog)s' % dict(prog=self._prog) elif usage is None: prog = '%(prog)s' % dict(prog=self._prog) # build full usage string action_usage = self._format_actions_usage(actions, groups) # NEW usage = ' '.join([s for s in [prog, action_usage] if s]) # omit the long line wrapping code # prefix with 'usage:' return '%s%s ' % (prefix, usage) parser = argparse.ArgumentParser(formatter_class=Formatter) |
它产生一个使用行,比如:
1 | usage: stack26985650.py [-h] positional [-o OPTIONAL [OPTIONAL ...]] |
不要使用