Ricerca…


introduzione

La maggior parte degli strumenti a riga di comando si basano su argomenti passati al programma al momento dell'esecuzione. Invece di richiedere input, questi programmi si aspettano che vengano impostati dati o flag specifici (che diventano booleani). Ciò consente sia all'utente che ad altri programmi di eseguire il file Python passandogli i dati all'avvio. Questa sezione spiega e dimostra l'implementazione e l'uso degli argomenti della riga di comando in Python.

Ciao mondo in argparse

Il seguente programma dice ciao all'utente. Prende un argomento posizionale, il nome dell'utente e può anche essere detto il saluto.

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('name', 
    help='name of user'
)

parser.add_argument('-g', '--greeting', 
    default='Hello',
    help='optional alternate greeting'
)

args = parser.parse_args()

print("{greeting}, {name}!".format(
       greeting=args.greeting,
       name=args.name)
)
$ python hello.py --help
usage: hello.py [-h] [-g GREETING] name

positional arguments:
  name                  name of user

optional arguments:
  -h, --help            show this help message and exit
  -g GREETING, --greeting GREETING
                        optional alternate greeting
$ python hello.py world
Hello, world!
$ python hello.py John -g Howdy
Howdy, John!

Per maggiori dettagli si prega di leggere la documentazione di argparse .

Esempio di base con docopt

docopt trasforma l'argomento della riga di comando in analisi. Invece di analizzare gli argomenti, basta scrivere la stringa di utilizzo per il proprio programma e docopt analizza la stringa di utilizzo e la utilizza per estrarre gli argomenti della riga di comando.

"""
Usage:
    script_name.py [-a] [-b] <path>

Options:
    -a            Print all the things.
    -b            Get more bees into the path.
"""
from docopt import docopt


if __name__ == "__main__":
    args = docopt(__doc__)
    import pprint; pprint.pprint(args)

Esecuzioni di esempio:

$ python script_name.py
Usage:
    script_name.py [-a] [-b] <path>
$ python script_name.py something
{'-a': False,
 '-b': False,
 '<path>': 'something'}
$ python script_name.py something -a
{'-a': True,
 '-b': False,
 '<path>': 'something'}
$ python script_name.py -b something -a
{'-a': True,
 '-b': True,
 '<path>': 'something'}

Impostazione di argomenti mutuamente esclusivi con argparse

Se vuoi che due o più argomenti si escludano a vicenda. È possibile utilizzare la funzione argparse.ArgumentParser.add_mutually_exclusive_group() . Nell'esempio seguente, possono esistere foo o bar ma non entrambi allo stesso tempo.

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-f", "--foo")
group.add_argument("-b", "--bar")
args = parser.parse_args()
print "foo = ", args.foo
print "bar = ", args.bar

Se si tenta di eseguire lo script specificando entrambi --bar argomenti --foo e --bar , lo script si lamenterà con il messaggio seguente.

error: argument -b/--bar: not allowed with argument -f/--foo

Utilizzo degli argomenti della riga di comando con argv

Ogni volta che uno script Python viene richiamato dalla riga di comando, l'utente può fornire ulteriori argomenti della riga di comando che verranno passati allo script. Questi argomenti saranno disponibili per il programmatore dalla variabile di sistema sys.argv ("argv" è un nome tradizionale utilizzato nella maggior parte dei linguaggi di programmazione e significa " arg ument v ector").

Per convenzione, il primo elemento nell'elenco sys.argv è il nome dello stesso script Python, mentre il resto degli elementi sono i token passati dall'utente quando si richiama lo script.

# cli.py
import sys
print(sys.argv)

$ python cli.py
=> ['cli.py']

$ python cli.py fizz
=> ['cli.py', 'fizz']

$ python cli.py fizz buzz
=> ['cli.py', 'fizz', 'buzz']

Ecco un altro esempio di come usare argv . Prima rimuoviamo l'elemento iniziale di sys.argv perché contiene il nome dello script. Quindi combiniamo il resto degli argomenti in una singola frase e infine stampiamo quella frase anteponendo il nome dell'utente attualmente loggato (in modo che emuli un programma di chat).

import getpass
import sys

words = sys.argv[1:]
sentence = " ".join(words)
print("[%s] %s" % (getpass.getuser(), sentence))

L'algoritmo comunemente usato quando "manualmente" l'analisi di un numero di argomenti non posizionali è quello di scorrere l'elenco sys.argv . Un modo è quello di andare oltre la lista e pop ogni elemento di esso:

# reverse and copy sys.argv
argv = reversed(sys.argv)
# extract the first element
arg = argv.pop()
# stop iterating when there's no more args to pop()
while len(argv) > 0:
    if arg in ('-f', '--foo'):
        print('seen foo!')
    elif arg in ('-b', '--bar'):
        print('seen bar!')
    elif arg in ('-a', '--with-arg'):
        arg = arg.pop()
        print('seen value: {}'.format(arg))
    # get the next value
    arg = argv.pop()

Messaggio di errore del parser personalizzato con argparse

È possibile creare messaggi di errore parser in base alle esigenze del proprio script. Questo è attraverso la funzione argparse.ArgumentParser.error . L'esempio seguente mostra lo script stampa di un utilizzo e un messaggio di errore a stderr quando --foo è dato, ma non --bar .

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-f", "--foo")
parser.add_argument("-b", "--bar")
args = parser.parse_args()
if args.foo and args.bar is None:
    parser.error("--foo requires --bar. You did not specify bar.")

print "foo =", args.foo
print "bar =", args.bar

Supponendo che il nome dello script sia sample.py, eseguiamo: python sample.py --foo ds_in_fridge

Lo script si lamenterà con quanto segue:

usage: sample.py [-h] [-f FOO] [-b BAR]
sample.py: error: --foo requires --bar. You did not specify bar.

Raggruppamento concettuale di argomenti con argparse.add_argument_group ()

Quando crei Argparse ArgumentParser () ed esegui il tuo programma con '-h' ottieni un messaggio di utilizzo automatico che spiega quali argomenti puoi eseguire con il tuo software. Per impostazione predefinita, gli argomenti posizionali e gli argomenti condizionali sono separati in due categorie, ad esempio, qui c'è un piccolo script (example.py) e l'output quando si esegue python example.py -h .

import argparse

parser = argparse.ArgumentParser(description='Simple example')
parser.add_argument('name', help='Who to greet', default='World')
parser.add_argument('--bar_this')
parser.add_argument('--bar_that')
parser.add_argument('--foo_this')
parser.add_argument('--foo_that')
args = parser.parse_args()
usage: example.py [-h] [--bar_this BAR_THIS] [--bar_that BAR_THAT]
                        [--foo_this FOO_THIS] [--foo_that FOO_THAT]
                        name

Simple example

positional arguments:
  name                 Who to greet

optional arguments:
  -h, --help           show this help message and exit
  --bar_this BAR_THIS
  --bar_that BAR_THAT
  --foo_this FOO_THIS
  --foo_that FOO_THAT

Ci sono alcune situazioni in cui vuoi separare i tuoi argomenti in ulteriori sezioni concettuali per aiutare il tuo utente. Ad esempio, potresti desiderare di avere tutte le opzioni di input in un gruppo e tutte le opzioni di output in un'altra. L'esempio sopra può essere regolato per separare gli --foo_* dagli argomenti --bar_* modo.

import argparse

parser = argparse.ArgumentParser(description='Simple example')
parser.add_argument('name', help='Who to greet', default='World')
# Create two argument groups
foo_group = parser.add_argument_group(title='Foo options')
bar_group = parser.add_argument_group(title='Bar options')
# Add arguments to those groups
foo_group.add_argument('--bar_this')
foo_group.add_argument('--bar_that')
bar_group.add_argument('--foo_this')
bar_group.add_argument('--foo_that')
args = parser.parse_args()

Che produce questo output quando python example.py -h viene eseguito:

usage: example.py [-h] [--bar_this BAR_THIS] [--bar_that BAR_THAT]
                        [--foo_this FOO_THIS] [--foo_that FOO_THAT]
                        name

Simple example

positional arguments:
  name                 Who to greet

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

Foo options:
  --bar_this BAR_THIS
  --bar_that BAR_THAT

Bar options:
  --foo_this FOO_THIS
  --foo_that FOO_THAT

Esempio avanzato con docopt e docopt_dispatch

Come con docopt, con [docopt_dispatch] costruisci il tuo --help nella variabile __doc__ del tuo modulo entry-point. Lì, si chiama dispatch con la stringa doc come argomento, quindi può eseguire il parser su di esso.

Fatto questo, invece di gestire manualmente gli argomenti (che di solito finiscono in una struttura ciclomatic se / else alta), lo si lascia alla distribuzione dando solo come si desidera gestire l'insieme di argomenti.

Questo è il motivo per cui è utilizzato il decoratore dispatch.on : gli si fornisce l'argomento o la sequenza di argomenti che devono attivare la funzione e tale funzione verrà eseguita con i valori corrispondenti come parametri.

"""Run something in development or production mode.

Usage: run.py --development <host> <port>
       run.py --production <host> <port>
       run.py items add <item>
       run.py items delete <item>

"""
from docopt_dispatch import dispatch

@dispatch.on('--development')
def development(host, port, **kwargs):
    print('in *development* mode')

@dispatch.on('--production')
def development(host, port, **kwargs):
    print('in *production* mode')

@dispatch.on('items', 'add')
def items_add(item, **kwargs):
    print('adding item...')

@dispatch.on('items', 'delete')
def items_delete(item, **kwargs):
    print('deleting item...')

if __name__ == '__main__':
    dispatch(__doc__)


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow