Python: Prettier argparse output

时间:2016-02-12 21:11:25

标签: python argparse

I'm writing a Django management command. When I try to run it with required args omitted, I get this output:

def key_for_min_value(hash)
  lowest_key = nil
  lowest_value = Float::INFINITY
  hash.each do |k, v|
    if v < lowest_value
      lowest_value = v
      lowest_key = k
    end
  end
  lowest_key
end

See how in some places the arg name appears on one line and the placeholder appears on the next. It's kind of hard to read. Any way to fix this?

Note: I'm not referring to the help text I provide argparse, this question pertains to the autogenerated help output that's based on the arguments I define.

3 个答案:

答案 0 :(得分:1)

问题在于格式化usage行的函数中的换行。

HelpFormatter._format_usage

不幸的是,这个功能很长很脆弱。它使用HelpFormatter._format_actions_usage格式化用法。函数的其余部分将此文本拆分为行,并考虑_width和当前indent。它在空格上分裂,无论它们是在参数之间还是在flag和metavar之间。

你的部分问题是大缩进:

usage: manage.py generatebooktemplate 

generatebooktemplate可能是子命令(subparser)名称。

另一个问题是文字宽度。据说这是可控的,但如另一个答案中所示需要一些技巧。

您可以编写自定义usage行,但我认为这并不能让您控制换行符。 RawHelpRawDescription帮助类不适用,因为usage使用自己的行格式化程序。

您可以使用参数metavar参数,缩短用法中的名称。您还可以使用定义这些参数的顺序。

在测试代码中,使用

parser.format_usage()
parser.print_usage()

查看使用行而不必生成错误。

最后,您可以继承HelpFormatter并重写_format_usage以满足您的需求。如果您不使用任何mutual_exclusive_groups,将会更容易。

答案 1 :(得分:0)

There is the formatter class of argparse which you can use to define your own help text formatting.

See also Python argparse: How to insert newline in the help text?

答案 2 :(得分:0)

Help output is formatted by <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js"></script> (the default) or a subclass specified by the HelpFormatter argument. Officially, only the names of the classes are considered part of the public API; how they actually work are implementation details and not guaranteed to remain the same.

formatter_class takes a HelpFormatter.__init__ argument, but there seems to be no way to actually pass a value to it. You can't even patch the instance, since only the class is stored and it is instantiated on-demand in various places. You might try the following:

width

to force a longer width. Scanning the code, I didn't seen anywhere that the from functools import partial p = ArgumentParser(formatter_class=partial(HelpFormatter, width=200)) value was used other than as a callable to instantiate it.

As an alternative, you can define a subclass of formatter_class and override its ArgumentParser method, which currently just instantiates a formatter with a single argument. Your subclass could provide a way of passing arguments to that call.