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?

584voto

Michał Kwiatkowski Punkte 8516

Versuchen Sie es mit RawTextHelpFormatter :

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

103voto

Anthon Punkte 58254

Wenn Sie nur die eine Option außer Kraft setzen wollen, sollten Sie nicht RawTextHelpFormatter . Stattdessen wird die Unterklasse HelpFormatter und bieten ein spezielles Intro für die Optionen, die "roh" behandelt werden sollen (ich verwende "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)

Und verwenden Sie es:

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

Alle anderen Aufrufe an .add_argument() wo die Hilfe nicht mit R| wird wie üblich umbrochen.

Dies ist Teil der meine Verbesserungen an argparse . Der vollständige SmartFormatter unterstützt auch das Hinzufügen die Standardwerte für alle Optionen und die Roheingabe der Beschreibung des Dienstprogramms. Die Vollversion hat eine eigene _split_lines Methode, so dass die Formatierung von z.B. Versionsstrings erhalten bleibt:

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

44voto

Wang Zong'an Punkte 1342

Eine weitere einfache Möglichkeit ist die Aufnahme von textwrap .

Zum Beispiel,

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

Auf diese Weise können wir den langen Leerraum vor jeder Ausgabezeile vermeiden.

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

15voto

flaz14 Punkte 806

Ich habe ein ähnliches Problem (Python 2.7.6) konfrontiert. Ich habe versucht, aufzubrechen Beschreibung Abschnitt in mehrere Zeilen mit RawTextHelpFormatter :

parser = ArgumentParser(description="""First paragraph 

                                       Second paragraph

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

options = parser.parse_args()

Und bekam:

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

First paragraph 

                        Second paragraph

                        Third paragraph

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

Also RawTextHelpFormatter ist keine Lösung. Denn die Beschreibung wird so gedruckt, wie sie im Quellcode erscheint, wobei alle Leerzeichen erhalten bleiben (ich möchte aus Gründen der Lesbarkeit zusätzliche Tabulatoren in meinem Quellcode behalten, aber ich möchte sie nicht alle drucken. Außerdem bricht der Rohformatierer eine Zeile nicht um, wenn sie zu lang ist, z. B. mehr als 80 Zeichen).

Dank an @Anton, der die richtige Richtung vorgab über . Diese Lösung muss jedoch geringfügig geändert werden, um Folgendes zu formatieren Beschreibung Abschnitt.

Auf jeden Fall wird ein benutzerdefinierter Formatierer benötigt. Ich habe das bestehende HelpFormatter Klasse und überschreibt _fill_text Methode wie folgt:

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

Vergleichen Sie mit dem Original-Quellcode, der von argparse Modul:

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)

Im ursprünglichen Code wird die gesamte Beschreibung umbrochen. Im obigen benutzerdefinierten Formatierer wird der gesamte Text in mehrere Abschnitte aufgeteilt, und jeder von ihnen wird unabhängig formatiert.

Also mit Hilfe eines benutzerdefinierten Formatierers:

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

options = parser.parse_args()

ist die Ausgabe:

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

First paragraph

Second paragraph

Third paragraph

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

12voto

Bernd Wechner Punkte 1484

Ich gebe zu, dass dies für mich eine sehr frustrierende Erfahrung war, so wie für viele andere auch, wenn man bedenkt, wie viele Lösungen gepostet wurden und wie oft ich diese Frage im Internet gestellt bekomme. Aber ich finde die meisten dieser Lösungen viel zu kompliziert für meine Vorlieben und ich möchte die einfachste Lösung, die ich dafür habe, mit Ihnen teilen.

Hier ist das Skript zur Veranschaulichung:

#!/usr/bin/python3
import textwrap
from argparse import ArgumentParser, HelpFormatter

class RawFormatter(HelpFormatter):
    def _fill_text(self, text, width, indent):
        return "\n".join([textwrap.fill(line, width) for line in textwrap.indent(textwrap.dedent(text), indent).splitlines()])

program_descripton = f'''
    FunkyTool v1.0

    Created by the Funky Guy on January 1 2020
    Copyright 2020. All rights reserved.

    Licensed under The Hippocratic License 2.1
    https://firstdonoharm.dev/

    Distributed on an "AS IS" basis without warranties
    or conditions of any kind, either express or implied.

    USAGE:
    '''

parser = ArgumentParser(description=program_descripton, formatter_class=RawFormatter)
args = parser.parse_args()

Und so sieht es aus in test.py :

$ ./test.py --help
usage: test.py [-h]

FunkyTool v1.0

Created by the Funky Guy on January 1 2020
Copyright 2020. All rights reserved.

Licensed under The Hippocratic License 2.1
https://firstdonoharm.dev/

Distributed on an "AS IS" basis without warranties
or conditions of any kind, either express or implied.

USAGE:

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

Alle grundlegenden Formatierungen in der ursprünglichen Beschreibung wurden beibehalten, und wir mussten leider einen benutzerdefinierten Formatierer verwenden, aber es ist ein Einzeiler. Es kann übersichtlicher geschrieben werden als:

class RawFormatter(HelpFormatter):
    def _fill_text(self, text, width, indent):
        text = textwrap.dedent(text)          # Strip the indent from the original python definition that plagues most of us.
        text = textwrap.indent(text, indent)  # Apply any requested indent.
        text = text.splitlines()              # Make a list of lines
        text = [textwrap.fill(line, width) for line in text] # Wrap each line 
        text = "\n".join(text)                # Join the lines again
        return text

Aber ich selbst bevorzuge es auf einer Linie.

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