497 Stimmen

Wie kann man Zeilenumbrüche in den argparse-Hilfetext einfügen?

Ich benutze argparse in Python 2.7 für das Parsen von Eingabeoptionen. Eine meiner Optionen ist eine Mehrfachauswahl. Ich möchte eine Liste im Hilfetext erstellen, z.B.

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

Allerdings, argparse entfernt alle Zeilenumbrüche und aufeinanderfolgende Leerzeichen. Das Ergebnis sieht wie folgt aus

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

Wie fügt man Zeilenumbrüche in den Hilfetext ein?

10voto

Diferante Punkte 21

Eine weitere einfache Möglichkeit, neue Zeilen zu erhalten, ist RawTextHelpFormatter und die Behandlung der Einrückung ist

import argparse

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

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

Die Ausgabe lautet

$ python2 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

3voto

ermitz Punkte 121

Ausgehend von dem oben beschriebenen SmartFomatter bin ich zu dieser Lösung gelangt:

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

Beachten Sie, dass das Argument formatter_class, das an den Parser der obersten Ebene übergeben wird, seltsamerweise nicht an die sub_parsers vererbt wird, sondern für jeden erstellten sub_parser erneut übergeben werden muss.

2voto

sdbbs Punkte 3111

Ich wollte sowohl manuelle Zeilenumbrüche in den Beschreibungstext haben, und Auto-Wrapping es; aber keiner der Vorschläge hier für mich gearbeitet - so endete ich modifizieren die SmartFormatter-Klasse in den Antworten hier gegeben; die Probleme mit der argparse-Methode-Namen nicht eine öffentliche API ungeachtet, hier ist, was ich habe (als eine Datei namens 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()

So funktioniert es in 2.7 und 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

1voto

Carson Punkte 3411

Vorwort

Für diese Frage, argparse.RawTextHelpFormatter ist für mich hilfreich.

Nun möchte ich Ihnen mitteilen, wie ich die argparse .

Ich weiß, dass es vielleicht nicht mit der Frage zusammenhängt,

aber diese Fragen beschäftigen mich schon seit einer Weile.

Deshalb möchte ich meine Erfahrungen weitergeben, in der Hoffnung, dass sie für jemanden hilfreich sind.

Jetzt geht's los.

Module von Drittanbietern

colorama : zum Ändern der Textfarbe: pip install colorama

Ermöglicht das Funktionieren von ANSI-Escape-Zeichenfolgen (zur Erzeugung von farbigem Terminaltext und Cursorpositionierung) unter MS Windows

Beispiel

import colorama
from colorama import Fore, Back
from pathlib import Path
from os import startfile, system

SCRIPT_DIR = Path(__file__).resolve().parent
TEMPLATE_DIR = SCRIPT_DIR.joinpath('.')

def main(args):
    ...

if __name__ == '__main__':
    colorama.init(autoreset=True)

    from argparse import ArgumentParser, RawTextHelpFormatter

    format_text = FormatText([(20, '<'), (60, '<')])
    yellow_dc = format_text.new_dc(fore_color=Fore.YELLOW)
    green_dc = format_text.new_dc(fore_color=Fore.GREEN)
    red_dc = format_text.new_dc(fore_color=Fore.RED, back_color=Back.LIGHTYELLOW_EX)

    script_description = \
        '\n'.join([desc for desc in
                   [f'\n{green_dc(f"python {Path(__file__).name} [REFERENCE TEMPLATE] [OUTPUT FILE NAME]")} to create template.',
                    f'{green_dc(f"python {Path(__file__).name} -l *")} to get all available template',
                    f'{green_dc(f"python {Path(__file__).name} -o open")} open template directory so that you can put your template file there.',
                    # <- add your own description
                    ]])
    arg_parser = ArgumentParser(description=yellow_dc('CREATE TEMPLATE TOOL'),
                                # conflict_handler='resolve',
                                usage=script_description, formatter_class=RawTextHelpFormatter)

    arg_parser.add_argument("ref", help="reference template", nargs='?')
    arg_parser.add_argument("outfile", help="output file name", nargs='?')
    arg_parser.add_argument("action_number", help="action number", nargs='?', type=int)
    arg_parser.add_argument('--list', "-l", dest='list',
                            help=f"example: {green_dc('-l *')} \n"
                                 "description: list current available template. (accept regex)")

    arg_parser.add_argument('--option', "-o", dest='option',
                            help='\n'.join([format_text(msg_data_list) for msg_data_list in [
                                ['example', 'description'],
                                [green_dc('-o open'), 'open template directory so that you can put your template file there.'],
                                [green_dc('-o run'), '...'],
                                [green_dc('-o ...'), '...'],
                                # <- add your own description
                            ]]))

    g_args = arg_parser.parse_args()
    task_run_list = [[False, lambda: startfile('.')] if g_args.option == 'open' else None,
                     [False, lambda: [print(template_file_path.stem) for template_file_path in TEMPLATE_DIR.glob(f'{g_args.list}.py')]] if g_args.list else None,
                     # <- add your own function
                     ]
    for leave_flag, func in [task_list for task_list in task_run_list if task_list]:
        func()
        if leave_flag:
            exit(0)

    # CHECK POSITIONAL ARGUMENTS
    for attr_name, value in vars(g_args).items():
        if attr_name.startswith('-') or value is not None:
            continue
        system('cls')
        print(f'error required values of {red_dc(attr_name)} is None')
        print(f"if you need help, please use help command to help you: {red_dc(f'python {__file__} -h')}")
        exit(-1)
    main(g_args)

Wenn die Klasse der FormatText ist die folgende

class FormatText:
    __slots__ = ['align_list']

    def __init__(self, align_list: list, autoreset=True):
        """
        USAGE::

            format_text = FormatText([(20, '<'), (60, '<')])
            red_dc = format_text.new_dc(fore_color=Fore.RED)
            print(red_dc(['column 1', 'column 2']))
            print(red_dc('good morning'))
        :param align_list:
        :param autoreset:
        """
        self.align_list = align_list
        colorama.init(autoreset=autoreset)

    def __call__(self, text_list: list):
        if len(text_list) != len(self.align_list):
            if isinstance(text_list, str):
                return text_list
            raise AttributeError
        return ' '.join(f'{txt:{flag}{int_align}}' for txt, (int_align, flag) in zip(text_list, self.align_list))

    def new_dc(self, fore_color: Fore = Fore.GREEN, back_color: Back = ""):  # DECORATOR
        """create a device context"""
        def wrap(msgs):
            return back_color + fore_color + self(msgs) + Fore.RESET
        return wrap

enter image description here

0voto

Troy Grosfield Punkte 1983

Der folgende Python 3-Formatierer fügt den Standardwert an, wenn einer vorhanden ist, und behält die Zeilenlänge bei.

from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, \ 
                     RawTextHelpFormatter
import textwrap

class CustomArgumentFormatter(ArgumentDefaultsHelpFormatter, RawTextHelpFormatter):
    """Formats argument help which maintains line length restrictions as well as appends default value if present."""

    def _split_lines(self, text, width):
        text = super()._split_lines(text, width)
        new_text = []

        # loop through all the lines to create the correct wrapping for each line segment.
        for line in text:
            if not line:
                # this would be a new line.
                new_text.append(line)
                continue

            # wrap the line's help segment which preserves new lines but ensures line lengths are
            # honored
            new_text.extend(textwrap.wrap(line, width))

        return new_text

Erstellen Sie dann Ihren Argument-Parser mit Ihrem neuen Formatierer:

my_arg_parser = ArgumentParser(formatter_class=CustomArgumentFormatter)
# ... add your arguments ...
print(my_arg_parser.format_help())

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X