Python argparse: ¿Cómo insertar una nueva línea en el texto de ayuda?
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
elimina todas las líneas nuevas y los espacios consecutivos. El resultado parece
~/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 nuevas líneas en el texto de ayuda?
5 answers
Intente usar RawTextHelpFormatter
:
from argparse import RawTextHelpFormatter
parser = ArgumentParser(description='test', formatter_class=RawTextHelpFormatter)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-23 19:23:51
Si solo desea anular la opción one, no debe usar RawTextHelpFormatter
. En su lugar, subclase el HelpFormatter
y proporcione una introducción especial para las opciones que deben manejarse " raw " (uso "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 úsalo:
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()
Cualquier otra llamada a .add_argument()
donde la ayuda no comience con R|
se empaquetará de forma normal.
Esto es parte de mis mejoras en argparse. El SmartFormatter completo también admite la adición
el valor predeterminado es todas las opciones, y la entrada sin procesar de la descripción de utilidades. La versión completa
tiene su propio método _split_lines
, por lo que cualquier formato realizado para, por ejemplo, cadenas de versión se conserva:
parser.add_argument('--version', '-v', action="version",
version="version...\n 42!")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-26 21:00:44
Otra manera 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, podemos 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 ...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-20 20:39:15
Me he enfrentado a un problema similar (Python 2.7.6). He intentado descomponer descripción sección en varias líneas usando RawTextHelpFormatter
:
parser = ArgumentParser(description="""First paragraph
Second paragraph
Third paragraph""",
usage='%(prog)s [OPTIONS]',
formatter_class=RawTextHelpFormatter)
options = parser.parse_args()
Y consiguió:
usage: play-with-argparse.py [OPTIONS] First paragraph Second paragraph Third paragraph optional arguments: -h, --help show this help message and exit
Así que RawTextHelpFormatter
no es una solución. Porque imprime la descripción tal como aparece en el código fuente, conservando todos los caracteres de espacio en blanco (quiero mantener pestañas adicionales en mi código fuente para facilitar la lectura, pero no quiero imprimirlos todos. También el formateador raw no envuelve la línea cuando es demasiado larga, más de 80 caracteres para ejemplo).
Gracias a @Anton quien inspiró la dirección correcta arriba. Pero esa solución necesita una ligera modificación con el fin de formatear descripción sección.
De todos modos, se necesita un formateador personalizado. Extendí la clase HelpFormatter
existente y anulé el método _fill_text
de esta manera:
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 la descripción completa está siendo empaquetada. En la costumbre formateador por encima de todo el texto se divide en varios trozos, y cada uno de ellos se formatea 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:48
Quería tener tanto saltos de línea manuales en el texto de la descripción, y el ajuste automático de la misma; pero ninguna de las sugerencias aquí funcionó para mí - así que terminé modificando la clase SmartFormatter dada en las respuestas aquí; los problemas con los nombres de los métodos argparse no siendo una API pública, 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()
Así es como 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-31 11:01:04