Pregunta

Estoy usando argparse en Python 2.7 para analizar las opciones de entrada. Una de mis opciones es una opción múltiple. Quiero hacer una lista en su texto de ayuda, por ejemplo.

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()

Sin embargo, argparse tiras de cada nueva línea y espacios consecutivos. El resultado se parece a

~/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

¿Cómo insertar saltos de línea en el texto de ayuda?

¿Fue útil?

Solución

Trate de usar RawTextHelpFormatter :

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

Otros consejos

Si lo que desea es anular la opción, no se debe utilizar RawTextHelpFormatter. En lugar subclase el HelpFormatter y proporcionar una introducción especial para las opciones que deben ser manejadas "en bruto" (utilizo "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)

Y utilizarlo:

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()

Las demás llamadas a .add_argument() donde la ayuda no se inicia con R| será envuelto con normalidad.

Esto es parte de mis mejoras en argparse . El SmartFormatter completo también admite la adición los valores por defecto a todas las opciones, y la entrada bruta de la descripción utilidades. La versión completa tiene su propio método _split_lines, de modo que ningún formato hacer para, por ejemplo, cadenas de versión se conserva:

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

Otra forma fácil de hacerlo es incluir TextWrap .

Por ejemplo,

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 ... '''))

De esta manera, se puede evitar el largo espacio vacío delante de cada línea de salida.

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 ...

He enfrentado problema similar (Python 2.7.6). He tratado de romper descripción en varias líneas utilizando RawTextHelpFormatter:

parser = ArgumentParser(description="""First paragraph 

                                       Second paragraph

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

options = parser.parse_args()

Y tiene:

usage: play-with-argparse.py [OPTIONS]

First paragraph 

                        Second paragraph

                        Third paragraph

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

Así RawTextHelpFormatter no es una solución. Debido a que imprime la descripción tal como aparece en el código fuente, la preservación de espacios en blanco (que quiero mantener las pestañas adicionales en mi código fuente para facilitar la lectura, pero no quiero imprimir a todos. También formateador prima no se ajusta lineal cuando se demasiado largo, más de 80 caracteres, por ejemplo).

Gracias a @Anton que inspiraron la dirección anterior . Pero esa solución debe ligera modificación con vistas a formato descripción .

En cualquier caso, se necesita formateador personalizado. Me extendió la clase existente y el método HelpFormatter _fill_text overrode como esto:

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

Comparar con el código fuente original procedente de argparse módulo:

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)

En el código original está siendo envuelto toda la descripción. En formateador personalizado por encima de todo el texto se divide en varias partes, y cada uno de ellos tiene el formato de forma independiente.

Así que con la ayuda de formateador personalizado:

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

options = parser.parse_args()

la salida es:

usage: play-with-argparse.py [OPTIONS]

First paragraph

Second paragraph

Third paragraph

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

Yo quería tener dos saltos de línea manuales en el texto de la descripción y de envolver automática de la misma; pero ninguna de las sugerencias aquí trabajado para mí - así que acabé modificando la clase SmartFormatter dada en las respuestas aquí; los problemas con los nombres de los métodos argparse no ser una API pública pesar de ello, aquí es lo que tengo (como un archivo llamado 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()

Esto es cómo funciona en 2.7 y 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

A partir de SmartFomatter descrito anteriormente, terminé a esa solución:

class SmartFormatter(argparse.HelpFormatter):
    '''
         Custom Help Formatter used to split help text when '\n' was 
         inserted in it.
    '''

    def _split_lines(self, text, width):
        r = []
        for t in text.splitlines(): r.extend(argparse.HelpFormatter._split_lines(self, t, width))
        return r

Tenga en cuenta que el argumento extrañamente formatter_class pasado al analizador de nivel superior no se inheritated por sub_parsers, uno debe pasar de nuevo por cada sub_parser creado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top