Argparse: modo di includere i valori predefiniti in '--help'?


307

Supponiamo che io abbia il seguente frammento di argparse:

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

Attualmente --helprestituisce:

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.

Preferirei qualcosa di simile:

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

Dai un'occhiata al codice del formatter di aiuto hanno rivelato opzioni limitate. Esiste un modo intelligente argparseper stampare il valore predefinito --scan-timein modo simile o dovrei semplicemente sottoclassare il helpformatter?


5
Potresti essere interessato a docopt . Non ho mai più guardato Argparse.
Paulo Scardine,

14
@PauloScardine - Essere integrati nella lingua è un grande vantaggio per argparse.
jordanm,

1
@PauloScardine: Inserire una libreria non standard nel mio progetto attuale sarà davvero una seccatura, ma di sicuro mi piace l'aspetto dell'output di docopt. Grazie per il consiglio!
JS.

@JS. dici "Inserire una libreria non standard nel mio progetto attuale sarà davvero una seccatura" Davvero? Ci sono molte librerie molto utili su pypi. Nel mio contesto è facile inserire una libreria non standard. È triste, se è difficile nel tuo contesto.
Guettli,

3
@guettli: quel progetto era per un progetto commerciale incorporato. Hai ragione, l'installazione è stata facile. Ottenere l'approvazione dal legale aziendale è stato un incubo.
JS.

Risposte:


447

Usa il argparse.ArgumentDefaultsHelpFormatterformatter :

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

Per citare la documentazione:

L'altra classe di formattatore disponibile ArgumentDefaultsHelpFormatteraggiungerà informazioni sul valore predefinito di ciascuno degli argomenti.

Si noti che ciò si applica solo agli argomenti che hanno definito il testo di aiuto ; senza alcun helpvalore per un argomento, non c'è un messaggio di aiuto per aggiungere informazioni sul valore predefinito a .

L'output esatto per l'opzione tempo di scansione diventa quindi:

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

12
Posso controllare che solo gli argomenti con esplicito default=mostrino il valore predefinito? Dal momento che non mi piacciono i testi "default: Nessuno".
ziyuang,

14
È possibile impostare la defaulta SUPPRESS: default=argparse.SUPPRESS. Si noti che in tal caso nessun attributo verrà aggiunto al risultato dello spazio dei nomi se tale argomento è stato omesso, consultare la defaultdocumentazione .
Martijn Pieters

4
Si noti che è necessario specificarlo anche per ogni sub-parser creato.
KomodoDave,

1
Quindi creare una nuova domanda, incluso un esempio riproducibile minimo che dimostra il problema. Come ho detto, funziona per me con Python 2.7.
Martijn Pieters

3
@ David Stavo avendo lo stesso problema. Aggiungi l' helpargomento add_argumente dovrebbe funzionare.
Pablo Díaz ogni

190

Aggiungi '%(default)s'al parametro di aiuto per controllare ciò che viene visualizzato.

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

9
Mi piace questa opzione perché avevo già usato format_class = argparse.RawTestHelpFormatter e non avevo voglia di andare in giro con OOP.
mqsoh

23
Non dimenticare di includere la variabile "tipo" nella stringa di formattazione, ad esempio "% (impostazione predefinita) s" per una stringa o "% (impostazione predefinita) d" per una cifra.
strongMA,

1
Mi piace molto questa soluzione, è molto più semplice e non devo gestire esplicitamente argomenti senza valori predefiniti.
void.pointer

@mqsoh ereditarietà multipla in realtà solo ha funzionato, ma purtroppo non è API pubblica: stackoverflow.com/a/52025430/895245
Ciro Santilli郝海东冠状病六四事件法轮功

1
Mi piace perché cambiare la classe del formatter aggiunge un sacco di "(default: Nessuno)" ovunque che sta ingombrando l'aiuto.
6005

11

Classe wrapper

Questo è l'approccio più affidabile e DRY che ho trovato finora sia per mostrare i valori predefiniti sia per usare un altro formattatore come argparse.RawTextHelpFormatterallo stesso tempo:

#!/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())

Produzione:

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+ RawTextHelpFormattereredità multipla

L'ereditarietà multipla funziona, ma non sembra essere un'API pubblica:

#!/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()

Produzione:

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)

Funziona semplicemente perché, come possiamo vedere banalmente dalle fonti https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648 che:

  • RawTextHelpFormatter attrezzi _split_lines
  • ArgumentDefaultsHelpFormatter attrezzi _get_help_string

quindi possiamo indovinare che funzioneranno bene insieme.

Tuttavia, questa non sembra essere un'API pubblica, e nemmeno i metodi di formatter_class, quindi non penso che ci sia un modo API pubblico per farlo attualmente. argparsedocstring dice:

Tutte le altre classi in questo modulo sono considerate dettagli di implementazione. (Si noti inoltre che HelpFormatter e RawDescriptionHelpFormatter sono considerati pubblici solo come nomi di oggetto: l'API degli oggetti di formattazione è ancora considerata un dettaglio di implementazione.)

Vedi anche: Personalizza il messaggio di aiuto di argparse

Testato su Python 3.6.5.


1
Grande ! Finalmente hanno sia il docstring formattato che gli argomenti predefiniti stampati. Grazie
Sylvain il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.