2015-12-31 30 views
5

Sono interessato all'utilizzo del formattatore della classe ArgumentDefaultsHelpFormatter di argparse (il mio programma ha diversi sottocomandi). Per impostazione predefinita, gli argomenti di input e output sono impostati rispettivamente su sys.stdin e sys.stdout. Tuttavia, la formattazione di questi due argomenti potrebbe essere un po 'di confusione per gli utenti (es. (Default:', mode 'r' a 0x10028e0c0>). C'è un modo per modificare in modo specifico e semplice il formato di output per questi due argomenti qualcosa come 'default: STDIN' o? 'default: STDOUT'Argparse e ArgumentDefaultsHelpFormatter. Formattazione dei valori predefiniti quando sys.stdin/stdout sono selezionati come predefiniti

Grazie

import sys 
import argparse 

parser = argparse.ArgumentParser(prog='PROG', 
           formatter_class=argparse.ArgumentDefaultsHelpFormatter) 

parser.add_argument('--infile', 
       '-i', 
       metavar='File', 
       help='The input file/stream.', 
       default=sys.stdin, 
       type=argparse.FileType('r'), 
       required=False) 

parser.add_argument('--outfile', 
       '-o', 
       metavar='File', 
       help='The output file/stream.', 
       default=sys.stdout, 
       type=argparse.FileType('r'), 
       required=False) 

parser.add_argument('--whatever-arg', 
       '-w', 
       type=str, 
       default='any', 
       help='Change something', 
       required=False) 


args = parser.parse_args() 
parser.print_help() 

che dà:

usage: PROG [-h] [--infile File] [--outfile File] 
      [--whatever-arg WHATEVER_ARG] 

optional arguments: 
    -h, --help   show this help message and exit 
    --infile File, -i File 
         The input file/stream. (default: <open file '<stdin>', 
         mode 'r' at 0x10028e0c0>) 
    --outfile File, -o File 
         The output file/stream. (default: <open file 
         '<stdout>', mode 'w' at 0x10028e150>) 
    --whatever-arg WHATEVER_ARG, -w WHATEVER_ARG 
         Change something (default: any) 
+0

Non sarebbe più semplice utilizzare il formattatore predefinito ed elencare esplicitamente i valori predefiniti nella guida?Un'altra opzione è quella di saltare 'FileType', e aprire i file te stesso in seguito. 'FileType' è conveniente per piccoli script, non così buono per quelli grandi (in cui è necessario un maggiore controllo su quando i file sono aperti). – hpaulj

+0

Il mio programma contiene circa 30 sottoprogrammi tutti con un proprio set di argomenti. Pertanto è molto conveniente utilizzare la formattazione con valori predefiniti. Posso saltare il FileType ma in tal caso non trarrò vantaggio dal controllo del file argparse. – user451460

+0

Quindi la personalizzazione del metodo '_get_help_string' funziona. Questo è tutto ciò che questa classe di formattazione predefinita fa comunque. – hpaulj

risposta

3

È possibile sottoclasse ArgumentDefaultsHelpFormatter a fare quello che vuoi

.
from argparse import ArgumentDefaultsHelpFormatter,RawDescriptionHelpFormatter 

class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter): 
    def _get_help_string(self, action): 
     help = action.help 
     if '%(default)' not in action.help: 
      if action.default is not argparse.SUPPRESS: 
       defaulting_nargs = [argparse.OPTIONAL, argparse.ZERO_OR_MORE] 
       if action.option_strings or action.nargs in defaulting_nargs: 
        if type(action.default) == type(sys.stdin): 
         print action.default.name 
         help += ' (default: ' + str(action.default.name) + ')' 
        else: 
         help += ' (default: %(default)s)' 
     return help 

parser = argparse.ArgumentParser(prog='PROG', formatter_class=CustomFormatter) 

risultato per me è:

optional arguments: 
    -h, --help   show this help message and exit 
    --infile File, -i File 
         The input file/stream. (default: <stdin>) 
    --outfile File, -o File 
         The output file/stream. (default: <stdout>) 
    --whatever-arg WHATEVER_ARG, -w WHATEVER_ARG 
         Change something (default: any) 
+0

Rientro dopo che 'def' è disattivato. Altrimenti il ​​concetto è valido. – hpaulj

+0

Grazie mille per il vostro aiuto. – user451460

2

Se si dà default='-' invece di sys.stdin, il display aiuto sarebbe

the input file/stream. (default: -) 

Cioè, aiuto mostra la stringa di default, ma FileType converte '-' a stdin/out.

As A.H indica che è possibile personalizzare il metodo _get_help_string. Non importa quale classe si eredita dalla, dal momento che la modifica che il metodo è tutto ciò che fa ADHF:

class ArgumentDefaultsHelpFormatter(HelpFormatter): 
    """... 
    """ 
    def _get_help_string(self, action): 
     help = action.help 
     if '%(default)' not in action.help: 
      if action.default is not SUPPRESS: 
       defaulting_nargs = [OPTIONAL, ZERO_OR_MORE] 
       if action.option_strings or action.nargs in defaulting_nargs: 
        help += ' (default: %(default)s)' 
     return help 

E si noti che tutto questo non fa altro che modifica aggiungere una stringa al parametro help - solo il (default: %(default)s)

Ciò significa che è possibile ottenere un effetto simile regolando le proprie linee help, ad es.

parser.add_argument('--infile', 
       '-i', 
       metavar='File', 
       help='The input file/stream, (default: stdin).', 
       default='-', 
       type=argparse.FileType('r')) 

parser.add_argument('--whatever-arg', 
       '-w', 
       default='any', 
       help='Change something, (default: %(default)s)') 

In altre parole, consente di risparmiare la digitazione (default: %(default)s) per 28 dei tuoi argomenti.

Se non si è sicuri di personalizzare la classe HelpFormatter (sebbene questo sia ciò che gli sviluppatori consigliano - con le dovute precauzioni), è possibile modificare la propria configurazione. Ad esempio, rendono semplice funzione di supporto che aggiunge la stringa in più per ogni linea di aiuto:

def foohelp(astr): 
    return astr + ' (default: %(default)s)' 

arg1 = parser.add_argument('-f','--fooarg', help=foohelp('help string')) 

Parlando di cambiare l'impostazione a livello di codice, vale la pena notare che add_argument crea un oggetto Action. Puoi salvare un link, come ho fatto qui, e modificare i parametri.

arg1 = parser.add_argument('-f','--fooarg', help='help string') 
print arg1.help 
arg1.help = foohelp(arg1.help) # modify help after creation 
print arg1.help 

Con 30 argomenti probabilmente hanno fatto un sacco di copia-n-incolla per definirli, o writen diverse funzioni di aiuto per semplificare l'installazione. L'aggiunta della visualizzazione predefinita è solo un'altra di quelle attività. Puoi farlo durante l'installazione, oppure puoi farlo tramite un formattatore personalizzato.

+0

Queste sono anche soluzioni molto belle. Grazie mille per il vostro aiuto. – user451460