2009-08-11 2 views
5

Secondo PEP 257 la docstring dello script della riga di comando dovrebbe essere il suo messaggio di utilizzo.Come rispettare le docstring PEP 257 quando si utilizza il modulo optparse di Python?

La docstring di uno script (un programma stand-alone) dovrebbe essere utilizzabile come il suo messaggio di "utilizzo", stampato quando lo script viene invocato con argomenti non corretti o mancanti (o forse con una " -h "opzione, per" aiuto "). Tale documentazione deve documentare la funzione dello script e la sintassi della riga di comando, le variabili di ambiente e i file. messaggi di utilizzo possono essere abbastanza elaborata (diversi schermi pieno) e dovrebbero essere sufficienti per un nuovo utente di utilizzare il comando correttamente, così come una completa riferimento rapido a tutte le opzioni e gli argomenti per il sofisticato utente .

Quindi il mio docstring sarebbe simile a questa:

 
<tool name> <copyright info> 

Usage: <prog name> [options] [args] 

some text explaining the usage... 

Options: 
    -h, --help show this help message and exit 
    ... 

Ora voglio utilizzare il modulo optparse. optparse genera le "Opzioni" sezioni e un "utilizzo" spiega la sintassi della riga di comando:

from optparse import OptionParser 

if __name__ == "__main__": 
    parser = OptionParser() 
    (options, args) = parser.parse_args() 

Quindi chiamare lo script con le stampe bandiera "-h":

 
Usage: script.py [options] 

Options: 
    -h, --help show this help message and exit 

Questo può essere modificato come segue:

parser = OptionParser(usage="Usage: %prog [options] [args]", 
         description="some text explaining the usage...") 

che si traduce in

 
Usage: script.py [options] [args] 

some text explaining the usage... 

Options: 
    -h, --help show this help message and exit 

Ma come posso usare la docstring qui? Passare la docstring come messaggio di utilizzo ha due problemi.

  1. optparse aggiunge "Utilizzo:" al docstring se non inizia con "Utilizzo:"
  2. Il segnaposto '% prog' deve essere utilizzato nella docstring

Risultato

Secondo le risposte sembra che non ci sia modo di riutilizzare la docstring intesa dal modulo optparse. Quindi l'opzione rimanente è di analizzare manualmente la docstring e costruire OptionParser. (Quindi accetterò la risposta di S.Loot)

La parte "Usage:" è introdotta da IndentedHelpFormatter che può essere sostituita con il parametro formatter in OptionParser .__ init __().

risposta

4

Scelta 1: copia e incolla. Non ASCIUTTO, ma lavorabile.

Scelta 2: Analizza la tua docstring per eliminare il paragrafo di descrizione. È sempre il secondo paragrafo, quindi puoi dividere su \ n \ n '.

usage, description= __doc__.split('\n\n')[:2] 

Dal optparse genera l'utilizzo, non si può decidere di fornire la sentenza utilizzo ad esso. La tua versione dell'uso è sbagliata. Se si insiste a fornire una stringa di utilizzo su optparse, lascerò che il lettore elabori come rimuovere "Usage: " dalla parte anteriore della stringa usage prodotta in precedenza.

+0

mi piace la seconda soluzione. Non molto pulito ma intelligente e pragmatico. –

+0

Poiché le righe vuote tra i paragrafi sono lo standard RST, questo salva l'esecuzione di un'analisi Docutils completa su __doc__ e ottiene quello che è, per definizione, il risultato previsto. –

+0

Questa potrebbe essere un'opzione per la descrizione. Ma non riesco ancora a riutilizzare la parte "Utilizzo" e optparse forza il messaggio a iniziare con "Uso:". – wierob

1

Penso che dovremmo essere ragionevoli riguardo al consiglio di questo PEP: penserei che sia corretto lasciare il modulo con __doc__ come breve descrizione che riassume l'uso prolungato. Ma se siete perfezionista:

'''<tool name> 

The full description and usage can be generated by optparse module. 

Description: ... 

''' 

... 

# Generate usage and options using optparse. 
usage, options = ... 

# Modify the docstring on the fly. 
docstring = __doc__.split('\n\n') 
docstring[1:2] = [__license__, usage, options] 
__doc__ = '\n\n'.join(docstring) 
6

ho scritto un modulo docopt di fare esattamente quello che vuoi - scrivere utilizzo-messaggio nella docstring e rimanere a secco. Permette anche di evitare di scrivere codice noioso OptionParser, poiché docopt sta generando il parser in base al messaggio di utilizzo.

Check it out: http://github.com/docopt/docopt

"""Naval Fate. 

Usage: 
    naval_fate.py ship new <name>... 
    naval_fate.py ship [<name>] move <x> <y> [--speed=<kn>] 
    naval_fate.py ship shoot <x> <y> 
    naval_fate.py mine (set|remove) <x> <y> [--moored|--drifting] 
    naval_fate.py -h | --help 
    naval_fate.py --version 

Options: 
    -h --help  Show this screen. 
    --version  Show version. 
    --speed=<kn> Speed in knots [default: 10]. 
    --moored  Moored (anchored) mine. 
    --drifting Drifting mine. 

""" 
from docopt import docopt 


if __name__ == '__main__': 
    arguments = docopt(__doc__, version='Naval Fate 2.0') 
    print(arguments)