我有这个代码,我总体上很满意:
import argparse
servers = [ "ApaServer", "BananServer", "GulServer", "SolServer", "RymdServer",
"SkeppServer", "HavsServer", "PiratServer", "SvartServer", "NattServer", "SovServer" ]
parser = argparse.ArgumentParser(description="A program to update components on servers.")
group = parser.add_mutually_exclusive_group()
group.add_argument('-l', '--list', dest="update", action='store_false', default=False, help='list server components')
group.add_argument('-u', '--updatepom', dest="update", action='store_true', help='update server components')
parser.add_argument('-o', '--only', nargs='*', choices=servers, help='Space separated list of case sensitive server names to process')
parser.add_argument('-s', '--skip', nargs='*', choices=servers, help='Space separated list of case sensitive server names to exclude from processing')
args = parser.parse_args()
我喜欢 choice=servers 为我验证输入中的服务器名称,这样我就不必这样做。然而,有这么多有效的选择使得帮助输出看起来很糟糕:
usage: args.py [-h] [-l | -u]
[-o [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]]]
[-s [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]]]
A program to update components on servers.
optional arguments:
-h, --help show this help message and exit
-l, --list list server components
-u, --updatepom update server components
-o [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]], --only [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]]
Space separated list of case sensitive server names to
process
-s [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]], --skip [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]]
Space separated list of case sensitive server names to
exclude from processing
如果我想要,你会推荐哪种方式:
servers
中。奖金:
追加
我尝试使用 michaelfilms 建议,其中
-o
-s
选项从上面的输出中删除,并添加了这部分:
server optional arguments:
Valid server names are: ApaServer, BananServer, GulServer, SolServer,
RymdServer, SkeppServer, HavsServer, PiratServer, SvartServer,
NattServer, SovServer
我认为它看起来不错,但我确实需要为
-o
和 -s
选项提供帮助,否则用户不会知道它们。所以我还没有完全使用这种方法。
我基本上重复了欧内斯特所说的 - 为了避免丑陋的长选择列表,为基于选择的参数设置
metavar=''
(尽管它不会消除参数和逗号之间的空格(例如 -o ,
相反) -o,
)。
然后,您可以在一般描述中详细描述可用选项(如果您希望以明显的缩进列出它们,
RawDescriptionHelpFormatter
在这里很有用)。
此代码:
import argparse
servers = [ "ApaServer", "BananServer", "GulServer", "SolServer", "RymdServer",
"SkeppServer", "HavsServer", "PiratServer", "SvartServer", "NattServer", "SovServer" ]
parser = argparse.ArgumentParser(description="A program to update components on servers.")
group = parser.add_mutually_exclusive_group()
group.add_argument('-l', '--list', dest="update", action='store_false', default=False, help='list server components')
group.add_argument('-u', '--updatepom', dest="update", action='store_true', help='update server components')
parser.add_argument('-o', '--only', choices=servers, help='Space separated list of case sensitive server names to process. Allowed values are '+', '.join(servers), metavar='')
parser.add_argument('-s', '--skip', choices=servers, help='Space separated list of case sensitive server names to exclude from processing. Allowed values are '+', '.join(servers), metavar='')
args = parser.parse_args()
产生以下帮助输出:
usage: run.py [-h] [-l | -u] [-o] [-s]
A program to update components on servers.
optional arguments:
-h, --help show this help message and exit
-l, --list list server components
-u, --updatepom update server components
-o , --only Space separated list of case sensitive server names to
process. Allowed values are ApaServer, BananServer,
GulServer, SolServer, RymdServer, SkeppServer, HavsServer,
PiratServer, SvartServer, NattServer, SovServer
-s , --skip Space separated list of case sensitive server names to
exclude from processing. Allowed values are ApaServer,
BananServer, GulServer, SolServer, RymdServer, SkeppServer,
HavsServer, PiratServer, SvartServer, NattServer, SovServer
这希望是原始帖子正在寻找的内容。
我也有同样的问题,作为解决方法,我使用结语来描述每个选项。 我必须使用 argparse.RawTextHelpFormatter,它可以让您指定 Epilog 已预先格式化。
def choicesDescriptions():
return """
Choices supports the following:
choice1 - the FIRST option
choice2 - the SECOND option
...
choiceN - the Nth option
"""
def getChoices():
return ["choice1", "choice2", ..., "choiceN"]
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, epilog=choicesDescriptions())
parser.add_argument(
'choices',
choices=getChoices(),
help='Arg choice. See the choices options below'
)
args = parser.parse_args()
print(args)
这在选项列表非常长的情况下没有帮助,就像原来的问题一样,但对于像我这样遇到这个问题的人来说,寻找一种将中等长的选项字符串分成两行的方法,这里是我的解决方案:
import argparse
class CustomFormatter(argparse.HelpFormatter):
"""Custom formatter for setting argparse formatter_class. Identical to the
default formatter, except that very long option strings are split into two
lines.
"""
def _format_action_invocation(self, action):
if not action.option_strings:
metavar, = self._metavar_formatter(action, action.dest)(1)
return metavar
else:
parts = []
# if the Optional doesn't take a value, format is:
# -s, --long
if action.nargs == 0:
parts.extend(action.option_strings)
# if the Optional takes a value, format is:
# -s ARGS, --long ARGS
else:
default = action.dest.upper()
args_string = self._format_args(action, default)
for option_string in action.option_strings:
parts.append('%s %s' % (option_string, args_string))
if sum(len(s) for s in parts) < self._width - (len(parts) - 1) * 2:
return ', '.join(parts)
else:
return ',\n '.join(parts)
此代码重写了默认的 argparse.HelpFormatter 方法 _format_action_invocation,并且除了最后四行之外与默认实现相同。
默认格式化程序行为:
parser = argparse.ArgumentParser(description="Argparse default formatter.")
parser.add_argument('-a', '--argument', help='not too long')
parser.add_argument('-u', '--ugly', choices=range(20), help='looks messy')
parser.print_help()
输出:
usage: test.py [-h] [-a ARGUMENT]
[-u {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}]
Argparse default formatter.
optional arguments:
-h, --help show this help message and exit
-a ARGUMENT, --argument ARGUMENT
not too long
-u {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}, --ugly {0,1,2,3,4,5,6,
7,8,9,10,11,12,13,14,15,16,17,18,19}
looks messy
自定义格式化程序行为:
parser = argparse.ArgumentParser(description="Argparse custom formatter.",
formatter_class=CustomFormatter)
parser.add_argument('-a', '--argument', help='not too long')
parser.add_argument('-l', '--less-ugly', choices=range(20), help='less messy')
输出:
usage: test.py [-h] [-a ARGUMENT]
[-l {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}]
Argparse custom formatter.
optional arguments:
-h, --help show this help message and exit
-a ARGUMENT, --argument ARGUMENT
not too long
-l {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19},
--less-ugly {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}
less messy
为什么不使用 parser.add_argument_group 为基于服务器的选项创建一个组,并给出一个描述 arg 显示可能的选择列表? 然后将 argparse.SUPPRESS 传递到每个单独选项的帮助中。 我相信这会给你你想要的。
要获得预期的输出,您需要子类化
argparse.HelpFormatter
并实现所需的格式。特别是,您需要实现自己的 _metavar_formatter
方法,该方法负责将所有选项连接到一个以逗号分隔的字符串中。
http://bugs.python.org/issue16468
argparse only supports iterable choices
是讨论选项格式的错误问题。 选项列表可以出现在 3 个位置:使用行、帮助行和错误消息。
解析器关心的只是进行
in
(__contains__
) 测试。 但对于格式化,长列表、无界“列表”(例如整数 >100)和其他不可迭代的对象会产生问题。 metavar
是当前用户可以解决大多数格式问题的方法(它可能对错误消息没有帮助)。 查看该问题,了解如何更改您自己的 argparse
版本。