Python3 Argparse 元变量括号解析异常
Python3 Argparse metavar brackets parsed weirdly
我在 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
注意第一行中括号的奇怪解析。
这是什么原因造成的,我该如何解决?
因为你希望有多个项目的可能性。使用 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
选项)。
是您的元变量中的 ()
导致了错误的使用。用法格式化程序使用 ()
标记需要互斥的组,然后删除多余的组。所以它试图保留 ( -o | -t)
,但将 (-o)
更改为 -o
。不幸的是,该代码无法区分它添加的代码和您通过元变量(或帮助行)添加的代码。
您的行格式为:
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 关注一个不同的使用问题,当使用行很长并且需要拆分时会出现这种问题。但是那个问题的最后 2 个帖子处理这个问题。
如果您不喜欢自动 usage
格式的限制,您可以给 parser
您自己的自定义 usage
参数。
我在 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 也不喜欢。
我在 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
注意第一行中括号的奇怪解析。
这是什么原因造成的,我该如何解决?
因为你希望有多个项目的可能性。使用 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
选项)。
是您的元变量中的 ()
导致了错误的使用。用法格式化程序使用 ()
标记需要互斥的组,然后删除多余的组。所以它试图保留 ( -o | -t)
,但将 (-o)
更改为 -o
。不幸的是,该代码无法区分它添加的代码和您通过元变量(或帮助行)添加的代码。
您的行格式为:
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 关注一个不同的使用问题,当使用行很长并且需要拆分时会出现这种问题。但是那个问题的最后 2 个帖子处理这个问题。
如果您不喜欢自动 usage
格式的限制,您可以给 parser
您自己的自定义 usage
参数。
我在 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 也不喜欢。