The*_*era 14 python argument-passing argparse
我正在尝试编写一个函数wo,你可以通过argparse解析可变数量的参数 - 我知道我可以通过这个来做nargs="+".遗憾的是,argparse帮助的工作方式(以及人们通常在CLI中编写参数的方式)将位置参数放在最后.这导致我的位置参数被捕获为可选参数的一部分.
#!/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
Run Code Online (Sandbox Code Playgroud)
运行此以./test.py -h显示以下使用说明:
usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] positional
Run Code Online (Sandbox Code Playgroud)
但如果我跑./test.py -o 0.21 0.11 0.33 0.13 100了就给我
test.py: error: too few arguments
Run Code Online (Sandbox Code Playgroud)
为了正确解析args,我必须运行 ./test.py 100 -o 0.21 0.11 0.33 0.13
那么我该怎么做:
make argparse重新格式化使用输出,以免误导,或者甚至更好:
-o如果它是列表中的最后一个,则告诉argparse不捕获可选参数的最后一个元素
?
hpa*_*ulj 17
有关于此的错误报告:http://bugs.python.org/issue9338
带有nargs ='?','*'或'+'的argparse选项不能跟随位置
一个简单的(用户)修复--用于将postionals与optionals分开:
./test.py -o 0.21 0.11 0.33 0.13 -- 100
Run Code Online (Sandbox Code Playgroud)
我写了一个补丁,保留了位置使用的一些参数.但这不是一件轻而易举的事.
至于更改使用线 - 最简单的方法是自己编写,例如:
usage: test.py [-h] positional [-o OPTIONAL [OPTIONAL ...]]
usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] -- positional
Run Code Online (Sandbox Code Playgroud)
我不建议在使用格式化程序中添加逻辑以进行此类更改.我认为这会变得太复杂.
另一个快速解决方法是将此位置转换为(必需)可选项.它为用户提供了完全自由的订单,可以减少混淆.如果您不想混淆'必需的可选',只需给它一个逻辑默认值.
usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] -p POSITIONAL
usage: test.py [-h] [-o OPTIONAL [OPTIONAL ...]] [-p POS_WITH_DEFAULT]
Run Code Online (Sandbox Code Playgroud)
对Help_Formatter的一个简单更改是简单地按照定义的顺序列出参数.修改格式化程序行为的常规方法是将其子类化,并更改一个或两个方法.这些方法中的大多数都是"私有"(_前缀),所以你要意识到未来的代码可能会发生变化(缓慢).
在此方法中,actions参数列表按其定义的顺序排列.默认行为是从'positionals'拆分'optionals',并在结尾处使用positionals重新组合列表.还有其他代码可以处理需要换行的长行.通常它会将位置放在一个单独的行上.我省略了.
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\n\n' % (prefix, usage)
parser = argparse.ArgumentParser(formatter_class=Formatter)
Run Code Online (Sandbox Code Playgroud)
这产生了一个使用线,如:
usage: stack26985650.py [-h] positional [-o OPTIONAL [OPTIONAL ...]]
Run Code Online (Sandbox Code Playgroud)