我正在使用Python的(2.7)argparse工具,并希望按选项自动按字母顺序排序。
默认情况下,帮助条目按照添加顺序排序*,如:
p = argparse.ArgumentParser(description='Load duration curves and other plots')
p.add_argument('--first', '-f', type=int, default=1, help='First Hour')
p.add_argument('--dur', '-d', type=int, default=-1, help='Duration in Hours. Use -1 for all')
p.add_argument('--title', '-t', help='Plot Title (for all plots), default=file name')
p.add_argument('--interp', '-i', action="store_true", default=True,
help='Use linear interpolation for smoother curves')
...
args = p.parse_args()
当被称为python script -h
时产生:
usage: script.py [-h] [--first FIRST] [--dur DUR] [--title TITLE] [--interp]
Load duration curves and other plots
optional arguments:
-h, --help show this help message and exit
--first FIRST, -f FIRST
First Hour
--dur DUR, -d DUR Duration in Hours. Use -1 for all
--title TITLE, -t TITLE
Plot Title (for all plots), default=file name
--interp, -i Use linear interpolation for smoother curves
是否可以按字母顺序自动对它们进行排序?这将是dur,first,h,interp,title。
*显然,解决方法是通过使用按字母顺序添加的顺序使用p.add_argument添加条目来手动维护,但我试图避免这样做。
答案 0 :(得分:19)
您可以通过提供自定义HelpFormatter
class来执行此操作;其内部正式无证。这意味着当你从Python版本到版本的兼容性时,你是独立的,但我发现界面非常稳定:
from argparse import HelpFormatter
from operator import attrgetter
class SortingHelpFormatter(HelpFormatter):
def add_arguments(self, actions):
actions = sorted(actions, key=attrgetter('option_strings'))
super(SortingHelpFormatter, self).add_arguments(actions)
p = argparse.ArgumentParser(...
formatter_class=SortingHelpFormatter,
)
在这里,我对选项字符串(('--dur', '-d')
等)进行排序,但您可以选择要排序的内容。这个简单的排序选项将单个破折号选项放在最后,例如-h
选项。
输出:
usage: [-h] [--first FIRST] [--dur DUR] [--title TITLE] [--interp]
Load duration curves and other plots
optional arguments:
--dur DUR, -d DUR Duration in Hours. Use -1 for all
--first FIRST, -f FIRST
First Hour
--interp, -i Use linear interpolation for smoother curves
--title TITLE, -t TITLE
Plot Title (for all plots), default=file name
-h, --help show this help message and exit
答案 1 :(得分:1)
创建ArgumentParser类时,可以传入帮助格式化程序: http://docs.python.org/library/argparse.html#formatter-class
显然你可以使用一个提供的格式化程序,但是如果不进行逆向工程,就不能覆盖和替换它们:
>>> h = argparse.ArgumentDefaultsHelpFormatter
>>> print h.__doc__
Help message formatter which adds default values to argument help.
Only the name of this class is considered a public API. All the methods
provided by the class are considered an implementation detail.
答案 2 :(得分:1)
另一种选择,绝对比@MartijnPieters提出的更丑陋的方式:
p = argparse.ArgumentParser()
#add arguements here
for g in p._action_groups:
g._group_actions.sort(key=lambda x:x.dest)
将它放在try
/ except
子句中可能会很好,因为它只是格式化帮助,因此如果这段代码失败,它对程序的执行并不重要AttributeError
或其他......
答案 3 :(得分:1)
这与@ mgilson的回答类似。我以为我之前发过这个帖子,但显然不是。
d = dict()
d['--first'] = ('-f', "type=int", "default=1", "help='First Hour'")
d['--dur'] = ('-d', type=int, default=-1, help='Duration in Hours. Use -1 for all')
# etc
for prim_option in sorted(d):
p.add_arguments(prim_option, *d[prim_option])
您可以调整词典中用作键的确切内容,以及sorted
的参数以及add_arguments
调用的确切结构,以获得所需的排序顺序。这遵循公开记录的argparse
接口,但确实在定义解析器的过程中添加了一个层。 (根据您的理念,从解析器的实现中分离选项信息可能是件好事。)
答案 4 :(得分:1)
帮助中参数的顺序由parser.format_help
方法确定:
Definition: parser.format_help(self)
Source:
def format_help(self):
formatter = self._get_formatter()
...
# positionals, optionals and user-defined groups
for action_group in self._action_groups:
formatter.start_section(action_group.title)
formatter.add_text(action_group.description)
formatter.add_arguments(action_group._group_actions)
formatter.end_section()
help
是通过获取formatter
对象,然后向其添加“部分”来创建的。这里循环遍历_action_groups
,将每个放在自己的部分中,并使用add_arguments
方法添加其操作(参数)。格式化程序是临时的,仅用于创建字符串(通常是多行)。
操作组包括默认的postionals
和optionals
,以及用户创建的任何内容。这些组仅用于帮助,不用于解析。因此action_group._group_actions
列表可以在不影响解析的情况下重新排序。 (解析器有自己的操作列表,parser._actions
)。
这证实了@ mgilson的观察结果p._actions
排序不影响帮助,但排序_group_actions
确实如此。
排序_actions
会影响usage
(无论是帮助还是独立):
# usage
formatter.add_usage(self.usage, self._actions,
self._mutually_exclusive_groups)
请注意,action_groups
未传递到使用部分。使用部分会重新排序其操作,首先显示optionals
,然后显示positionals
。
如果要控制定位的解析顺序及其在使用中的顺序,请在add_argument
阶段之前/期间对参数进行排序。
如果您只想控制帮助组中的顺序,则可以在调用格式化程序之前或在其中重新排序._group_actions
列表中的内容。
在usage
中有关于控制行动顺序的其他SO问题。例如,有些人不希望在positionals
之后订购optionals
。
我同意Formatter类很麻烦。但它在很大程度上与Parser类别分开。所以它可以被重写,对解析的影响很小。现有的Formatter子类只调整低级方法,控制换行和帮助行格式化。解析器和格式化程序之间的重要接口是format_usage
和format_help
方法,它们相对简单且高级。