Argparse: Möglichkeit, Standardwerte in '--help' aufzunehmen?


307

Angenommen, ich habe das folgende Argparse-Snippet:

diags.cmdln_parser.add_argument( '--scan-time',
                     action  = 'store',
                     nargs   = '?',
                     type    = int,
                     default = 5,
                     help    = "Wait SCAN-TIME seconds between status checks.")

Derzeit --helpkehrt zurück:

usage: connection_check.py [-h]
                             [--version] [--scan-time [SCAN_TIME]]

          Test the reliability/uptime of a connection.



optional arguments:
-h, --help            show this help message and exit
--version             show program's version number and exit
--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.

Ich würde so etwas bevorzugen wie:

--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.
                    (Default = 5)

Ein Blick auf den Formatierungscode der Hilfe ergab begrenzte Optionen. Gibt es eine clevere Möglichkeit, argparseden Standardwert für --scan-timeauf ähnliche Weise zu drucken , oder sollte ich den helpFormatierer einfach unterordnen?


5
Sie könnten an docopt interessiert sein . Ich habe Argparse nie wieder angeschaut.
Paulo Scardine

14
@PauloScardine - Die Integration in die Sprache ist ein großer Vorteil für argparse.
Jordanm

1
@PauloScardine: Das Ziehen einer nicht standardmäßigen Bibliothek in mein aktuelles Projekt wird zwar schmerzhaft sein, aber ich mag das Aussehen der Ausgabe von docopt. Danke für den Tipp!
JS.

@JS. Sie sagen: "Das Ziehen einer nicht standardmäßigen Bibliothek in mein aktuelles Projekt wird in der Tat schmerzhaft sein." Wirklich? Bei pypi gibt es viele sehr nützliche Bibliotheken. In meinem Kontext ist es einfach, eine nicht standardmäßige Bibliothek abzurufen. Es ist traurig, wenn es in Ihrem Kontext schwierig ist.
Guettli

3
@guettli: Dieses Projekt war für ein kommerzielles Embedded-Projekt. Die richtige Installation war einfach. Die Genehmigung von Corporate Legal zu erhalten, war ein Albtraum.
JS.

Antworten:


447

Verwenden Sie den argparse.ArgumentDefaultsHelpFormatterFormatierer :

parser = argparse.ArgumentParser(
    # ... other options ...
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

So zitieren Sie die Dokumentation:

Die andere verfügbare Formatierungsklasse ArgumentDefaultsHelpFormatterfügt Informationen zum Standardwert jedes der Argumente hinzu.

Beachten Sie, dass dies nur für Argumente gilt, für die Hilfetext definiert ist . ohne helpWert für ein Argument, gibt es keine Hilfemeldung Informationen über den Standardwert hinzuzufügen , zu .

Die genaue Ausgabe für Ihre Scan-Zeit-Option lautet dann:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)

12
Kann ich steuern, dass nur die Argumente mit einem expliziten default=Wert den Standardwert anzeigen? Da ich die 'default: None'-Texte nicht mag.
Ziyuang

14
Sie können das Set defaultan SUPPRESS: default=argparse.SUPPRESS. Beachten Sie, dass kein Attribut in diesem Fall wird auf das Namespace Ergebnis hinzugefügt werden , wenn dieses Argument weggelassen wurde, siehe die defaultDokumentation .
Martijn Pieters

4
Beachten Sie, dass Sie dies auch für jeden erstellten Subparser angeben müssen.
KomodoDave

1
Erstellen Sie dann eine neue Frage, einschließlich eines minimal reproduzierbaren Beispiels , das das Problem demonstriert. Wie gesagt, es funktioniert bei mir mit Python 2.7.
Martijn Pieters

3
@ David Ich hatte das gleiche Problem. Fügen Sie das helpArgument hinzu add_argumentund das sollte funktionieren.
Pablo Díaz Ogni

190

Fügen Sie '%(default)s'dem Hilfeparameter hinzu , um zu steuern, was angezeigt wird.

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")

9
Ich mag diese Option, weil ich bereits format_class = argparse.RawTestHelpFormatter verwendet hatte und keine Lust hatte, mit OOP herumzufurzeln.
mqsoh

23
Vergessen Sie nicht, die Variable 'type' in Ihre Formatierungszeichenfolge aufzunehmen - z. B. '% (Standard) s' für eine Zeichenfolge oder '% (Standard) d' für eine Ziffer.
strongMA

1
Ich mag diese Lösung viel besser, sie ist viel einfacher und ich muss nicht explizit mit Argumenten ohne Standardwerte umgehen.
void.pointer

@mqsoh Mehrfachvererbung hat eigentlich gerade funktioniert, ist aber leider keine öffentliche API: stackoverflow.com/a/52025430/895245
Ciro Santilli 法轮功 冠状 病 六四 事件 26

1
Ich mag das, weil das Ändern der Formatierungsklasse überall eine Reihe von "(Standard: Keine)" hinzufügt, was die Hilfe überfüllt.
6005

11

Wrapper-Klasse

Dies ist die zuverlässigste und DRY Ansatz , den ich bisher auf beide zeigen Standardwerte gefunden haben und eine andere Formatierer so verwenden , wie argparse.RawTextHelpFormatterzur gleichen Zeit:

#!/usr/bin/env python3

import argparse

class ArgumentParserWithDefaults(argparse.ArgumentParser):
    def add_argument(self, *args, help=None, default=None, **kwargs):
        if help is not None:
            kwargs['help'] = help
        if default is not None and args[0] != '-h':
            kwargs['default'] = default
            if help is not None:
                kwargs['help'] += ' Default: {}'.format(default)
        super().add_argument(*args, **kwargs)

parser = ArgumentParserWithDefaults(
    formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.add_argument('--no-default', help='''my help
for no-default''')
parser.add_argument('--no-help', default=101)

parser.print_help()
print()
print(parser.parse_args())

Ausgabe:

usage: main.py [-h] [-a A] [-b B] [--no-default NO_DEFAULT]
               [--no-help NO_HELP]

optional arguments:
  -h, --help            show this help message and exit
  -a A                  my help
                        for a Default: 13
  -b B                  my help
                        for b Default: 42
  --no-default NO_DEFAULT
                        my help
                        for no-default
  --no-help NO_HELP

Namespace(a=13, b=42, no_default=None, no_help=101)

ArgumentDefaultsHelpFormatter+ RawTextHelpFormatterMehrfachvererbung

Mehrfachvererbung funktioniert nur, scheint aber keine öffentliche API zu sein:

#!/usr/bin/env python3

import argparse

class RawTextArgumentDefaultsHelpFormatter(
        argparse.ArgumentDefaultsHelpFormatter,
        argparse.RawTextHelpFormatter
    ):
        pass

parser = argparse.ArgumentParser(
    formatter_class=RawTextArgumentDefaultsHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.print_help()

Ausgabe:

usage: a.py [-h] [-a A] [-b B]

optional arguments:
  -h, --help  show this help message and exit
  -a A        my help
              for a (default: 13)
  -b B        my help
              for b (default: 42)

Es funktioniert einfach, weil, wie wir aus den Quellen https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648 trivial sehen können, dass:

  • RawTextHelpFormatter Geräte _split_lines
  • ArgumentDefaultsHelpFormatter Geräte _get_help_string

Wir können also davon ausgehen, dass sie gut zusammenarbeiten werden.

Dies scheint jedoch keine öffentliche API zu sein, und die Methoden formatter_classauch nicht. Daher glaube ich nicht, dass es derzeit eine öffentliche API-Methode gibt, um dies zu tun. argparsedocstring sagt:

Alle anderen Klassen in diesem Modul werden als Implementierungsdetails betrachtet. (Beachten Sie auch, dass HelpFormatter und RawDescriptionHelpFormatter nur als Objektnamen als öffentlich betrachtet werden. Die API der Formatierungsobjekte wird weiterhin als Implementierungsdetail betrachtet.)

Siehe auch: Argparse-Hilfemeldung anpassen

Getestet auf Python 3.6.5.


1
Toll ! Lassen Sie zum Schluss sowohl die formatierte Dokumentzeichenfolge als auch die Standardargumente drucken. Danke
Sylvain
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.