我在python3中使用argparse,我得到一些奇怪的东西:
我使用的简短版代码是:
argparser = argparse.ArgumentParser(description='add/remove items')
argparser.add_argument('-a', action='append', metavar="Item(s)", help='add one or more items to the list')
argparser.add_argument('-r', action='append', metavar="Item(s)", help='remove one or more items from the list')
args = argparser.parse_args()
当我使用-h标志运行脚本时,我得到了这个输出:
usage: test.py [-h] [-a Items)] [-r Item(s]
add/remove items
optional arguments:
-h, --help show this help message and exit
-a CPE(s) add one or more items to the list
-r CPE(s) remove one or more items from the list
注意第一行中括号的奇怪解析。
是什么导致这种情况,我该如何解决这个问题?
答案 0 :(得分:2)
你的metavars中的()
导致了错误的使用。使用格式化程序使用()
标记需要互斥的组,然后删除多余的组。因此,它会尝试保留( -o | -t)
,但将(-o)
更改为-o
。不幸的是,代码不区分它添加的代码和通过metavar(或帮助代码行)添加的代码。
您的广告格式为:
usage: test.py [-h] [-a Item(s)] [-r Item(s)]
但它删除了我已用*:
替换的外部()
对
usage: test.py [-h] [-a Item*s)] [-r Item(s*]
http://bugs.python.org/issue11874侧重于不同的使用问题,当使用行很长并需要拆分时会出现问题。但该问题的最后两篇文章涉及这个问题。
如果您不喜欢自动usage
格式的限制,可以为parser
提供自己的自定义usage
参数。
答案 1 :(得分:1)
因为您希望有多个项目的可能性。使用argparse的另一种方法如下:
import argparse
argparser = argparse.ArgumentParser(description='add/remove items')
argparser.add_argument('-a', metavar="item", nargs="*", help='add one or more items to the list')
argparser.add_argument('-r', metavar="item", nargs="*", help='remove one or more items from the list')
args = argparser.parse_args()
关键是使用nargs="*"
(0个或更多个参数)。帮助变为:
usage: test.py [-h] [-a [item [item ...]]] [-r [item [item ...]]]
这样,您不必使用“Item(s)
”,也可以遵循标准做法。
PS :我明白你想做什么。使用action="append"
,您实际上允许用户指定多个-a
和-r
选项。在这种情况下,您绝对应该写"Item"
(而不是“Item(s)
”),因为每个选项都需要一个项目。这也解决了您的问题(您的帮助消息应该表明可以提供多个-a
和-r
选项。)
答案 2 :(得分:0)
我在python 2.7中的解决方案是重写argparse.format_usage()和argparse.format_help()。您对元变量进行编码,然后在argparse对其进行格式化后对其进行解码:
FIXES = (('\[', '%lb'), ('\]', '%rb'), ('\(', '%lp'), ('\)', '%rp'))
def encode_parens(text):
for orig, encoded in FIXES:
text = re.sub(orig, encoded, text)
return text
def decode_parens(text):
for orig, encoded in FIXES:
text = re.sub(encoded, orig[1:], text)
return text
class MyArgParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
super(MyArgParser, self).__init__(*args, **kwargs)
def format_usage(self, *args, **kwargs):
u = super(MyArgParser, self).format_usage(*args, **kwargs)
return decode_parens(u)
def format_help(self, *args, **kwargs):
h = super(MyArgParser, self).format_help(*args, **kwargs)
return decode_parens(h)
if __name__ == '__main__':
argparser = MyArgParser(description='add/remove items')
argparser.add_argument('-a', action='append', metavar=encode_parens("Item(s)"), help='add one or more items to the list')
argparser.add_argument('-r', action='append', metavar=encode_parens("Item(s)"), help='remove one or more items from the list')
args = argparser.parse_args()
这产生了您想要的:
usage: arg.py [-h] [-a Item(s)] [-r Item(s)]
它还修复了方括号,argparse也不喜欢。