本文翻译自:Python argparse: How to insert newline in the help text?

I'm using argparse for parsing input options. 在Python 2.7中使用argparse来解析输入选项。 One of my options is a multiple choice. 我的一个选择是多选。 I want to make a list in its help text, eg 我想在其帮助文本中列出一个列表,例如

from argparse import ArgumentParser

parser = ArgumentParser(description='test')

parser.add_argument('-g', choices=['a', 'b', 'g', 'd', 'e'], default='a',
    help="Some option, where\n"
         " a = alpha\n"
         " b = beta\n"
         " g = gamma\n"
         " d = delta\n"
         " e = epsilon")

parser.parse_args()

However, argparse strips all newlines and consecutive spaces. 但是, argparse所有换行符和连续空格。 The result looks like 结果看起来像


~/Downloads:52$ python2.7 x.py -h usage: x.py [-h] [-g {a,b,g,d,e}] test optional arguments: -h, --help show this help message and exit -g {a,b,g,d,e} Some option, where a = alpha b = beta g = gamma d = delta e = epsilon


How to insert newlines in the help text? 如何在帮助文本中插入换行符?


#1楼

参考:https://stackoom.com/question/GAWo/Python-argparse-如何在帮助文本中插入换行符


#2楼

If you just want to override the one option, you should not use RawTextHelpFormatter . 如果您只想覆盖一个选项,则不应使用RawTextHelpFormatter Instead subclass the HelpFormatter and provide a special intro for the options that should be handled "raw" (I use "R|rest of help" ): 而是HelpFormatter并为应该处理“raw”的选项提供一个特殊的介绍(我使用"R|rest of help" ):

import argparse

class SmartFormatter(argparse.HelpFormatter):

    def _split_lines(self, text, width):
        if text.startswith('R|'):
            return text[2:].splitlines()  
        # this is the RawTextHelpFormatter._split_lines
        return argparse.HelpFormatter._split_lines(self, text, width)

And use it: 并使用它:

from argparse import ArgumentParser

parser = ArgumentParser(description='test', formatter_class=SmartFormatter)

parser.add_argument('-g', choices=['a', 'b', 'g', 'd', 'e'], default='a',
    help="R|Some option, where\n"
         " a = alpha\n"
         " b = beta\n"
         " g = gamma\n"
         " d = delta\n"
         " e = epsilon")

parser.parse_args()

Any other calls to .add_argument() where the help does not start with R| .add_argument()任何其他调用,其中帮助不以R|开头 will be wrapped as normal. 将被包裹正常。

This is part of my improvements on argparse . 这是我对argparse的改进的一部分。 The full SmartFormatter also supports adding the defaults to all options, and raw input of the utilities description. 完整的SmartFormatter还支持将默认值添加到所有选项以及实用程序描述的原始输入。 The full version has its own _split_lines method, so that any formatting done to eg version strings is preserved: 完整版本有自己的_split_lines方法,因此可以保留对例如版本字符串所做的任何格式化:

parser.add_argument('--version', '-v', action="version",
                    version="version...\n   42!")

#3楼

I've faced similar issue (Python 2.7.6). 我遇到过类似的问题(Python 2.7.6)。 I've tried to break down description section into several lines using RawTextHelpFormatter : 我试图使用RawTextHelpFormatter描述部分分成几行:

parser = ArgumentParser(description="""First paragraph 

                                       Second paragraph

                                       Third paragraph""",  
                                       usage='%(prog)s [OPTIONS]', 
                                       formatter_class=RawTextHelpFormatter)

options = parser.parse_args()

And got: 得到了:


usage: play-with-argparse.py [OPTIONS] First paragraph Second paragraph Third paragraph optional arguments: -h, --help show this help message and exit


So RawTextHelpFormatter is not a solution. 所以RawTextHelpFormatter不是一个解决方案。 Because it prints description as it appears in source code, preserving all whitespace characters (I want to keep extra tabs in my source code for readability but I don't want to print them all. Also raw formatter doesn't wrap line when it is too long, more than 80 characters for example). 因为它打印源代码中显示的描述,保留所有空格字符(我想在我的源代码中保留额外的选项卡以便于阅读,但我不想全部打印它们。而且原始格式化程序在它是时不会换行太长,例如超过80个字符)。

Thanks to @Anton who inspired the right direction above . 由于@Anton谁启发了正确的方向之上 But that solution needs slight modification in order to format description section. 但是该解决方案需要稍微修改才能格式化描述部分。

Anyway, custom formatter is needed. 无论如何,需要自定义格式化程序。 I extended existing HelpFormatter class and overrode _fill_text method like this: 我扩展了现有的HelpFormatter类并_fill_text_fill_text方法,如下所示:

import textwrap as _textwrap
class MultilineFormatter(argparse.HelpFormatter):
    def _fill_text(self, text, width, indent):
        text = self._whitespace_matcher.sub(' ', text).strip()
        paragraphs = text.split('|n ')
        multiline_text = ''
        for paragraph in paragraphs:
            formatted_paragraph = _textwrap.fill(paragraph, width, initial_indent=indent, subsequent_indent=indent) + '\n\n'
            multiline_text = multiline_text + formatted_paragraph
        return multiline_text

Compare with the original source code coming from argparse module: 与来自argparse模块的原始源代码比较:

def _fill_text(self, text, width, indent):
    text = self._whitespace_matcher.sub(' ', text).strip()
    return _textwrap.fill(text, width, initial_indent=indent,
                                       subsequent_indent=indent)

In the original code the whole description is being wrapped. 在原始代码中,整个描述被包装。 In custom formatter above the whole text is split into several chunks, and each of them is formatted independently. 在上面的自定义格式化程序中,整个文本被分成几个块,每个块都是独立格式化的。

So with aid of custom formatter: 所以借助自定义格式化程序:

parser = ArgumentParser(description= """First paragraph 
                                        |n                              
                                        Second paragraph
                                        |n
                                        Third paragraph""",  
                usage='%(prog)s [OPTIONS]',
                formatter_class=MultilineFormatter)

options = parser.parse_args()

the output is: 输出是:


usage: play-with-argparse.py [OPTIONS] First paragraph Second paragraph Third paragraph optional arguments: -h, --help show this help message and exit



#4楼

Another easy way to do it is to include textwrap . 另一种简单的方法是包含textwrap

For example, 例如,

import argparse, textwrap
parser = argparse.ArgumentParser(description='some information',
        usage='use "python %(prog)s --help" for more information',
        formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument('--argument', default=somedefault, type=sometype,
        help= textwrap.dedent('''\
        First line
        Second line
        More lines ... '''))

In this way, we can avoid the long empty space in front of each output line. 这样,我们可以避免每条输出线前面的长空间。

usage: use "python your_python_program.py --help" for more information

Prepare input file

optional arguments:
-h, --help            show this help message and exit
--argument ARGUMENT
                      First line
                      Second line
                      More lines ...

#5楼

Try using RawTextHelpFormatter : 尝试使用RawTextHelpFormatter

from argparse import RawTextHelpFormatter
parser = ArgumentParser(description='test', formatter_class=RawTextHelpFormatter)

#6楼

I wanted to have both manual line breaks in the description text, and auto wrapping of it; 我想在描述文本中包含两个手动换行符,并自动换行; but none of the suggestions here worked for me - so I ended up modifying the SmartFormatter class given in the answers here; 但这里没有任何建议对我有用 - 所以我最后修改了答案中给出的SmartFormatter类; the issues with the argparse method names not being a public API notwithstanding, here is what I have (as a file called test.py ): 尽管argparse方法名称不是公共API的问题,但这就是我所拥有的(作为名为test.py的文件):

import argparse
from argparse import RawDescriptionHelpFormatter

# call with: python test.py -h

class SmartDescriptionFormatter(argparse.RawDescriptionHelpFormatter):
  #def _split_lines(self, text, width): # RawTextHelpFormatter, although function name might change depending on Python
  def _fill_text(self, text, width, indent): # RawDescriptionHelpFormatter, although function name might change depending on Python
    #print("splot",text)
    if text.startswith('R|'):
      paragraphs = text[2:].splitlines()
      rebroken = [argparse._textwrap.wrap(tpar, width) for tpar in paragraphs]
      #print(rebroken)
      rebrokenstr = []
      for tlinearr in rebroken:
        if (len(tlinearr) == 0):
          rebrokenstr.append("")
        else:
          for tlinepiece in tlinearr:
            rebrokenstr.append(tlinepiece)
      #print(rebrokenstr)
      return '\n'.join(rebrokenstr) #(argparse._textwrap.wrap(text[2:], width))
    # this is the RawTextHelpFormatter._split_lines
    #return argparse.HelpFormatter._split_lines(self, text, width)
    return argparse.RawDescriptionHelpFormatter._fill_text(self, text, width, indent)

parser = argparse.ArgumentParser(formatter_class=SmartDescriptionFormatter, description="""R|Blahbla bla blah blahh/blahbla (bla blah-blabla) a blahblah bl a blaha-blah .blah blah

Blah blah bla blahblah, bla blahblah blah blah bl blblah bl blahb; blah bl blah bl bl a blah, bla blahb bl:

  blah blahblah blah bl blah blahblah""")

options = parser.parse_args()

This is how it works in 2.7 and 3.4: 这是它在2.7和3.4中的工作原理:

$ python test.py -h
usage: test.py [-h]

Blahbla bla blah blahh/blahbla (bla blah-blabla) a blahblah bl a blaha-blah
.blah blah

Blah blah bla blahblah, bla blahblah blah blah bl blblah bl blahb; blah bl
blah bl bl a blah, bla blahb bl:

  blah blahblah blah bl blah blahblah

optional arguments:
  -h, --help  show this help message and exit