Risposte:
Questa risposta suggerisce optparse
quale sia appropriato per le versioni precedenti di Python. Per Python 2.7 e versioni successive, argparse
sostituisce optparse
. Vedi questa risposta per maggiori informazioni.
Come altri hanno sottolineato, è meglio andare con optparse su getopt. getopt è praticamente un mapping uno a uno delle funzioni standard della libreria C getopt (3) e non molto facile da usare.
optparse, pur essendo un po 'più prolisso, è molto meglio strutturato e più semplice da estendere in seguito.
Ecco una linea tipica per aggiungere un'opzione al tuo parser:
parser.add_option('-q', '--query',
action="store", dest="query",
help="query string", default="spam")
Parla praticamente da sé; al momento dell'elaborazione, accetterà -q o --query come opzioni, memorizzerà l'argomento in un attributo chiamato query e avrà un valore predefinito se non lo si specifica. È anche auto-documentante nel dichiarare l'argomento help (che verrà usato quando eseguito con -h / - help) proprio lì con l'opzione.
Di solito analizzi i tuoi argomenti con:
options, args = parser.parse_args()
Questo, per impostazione predefinita, analizzerà gli argomenti standard passati allo script (sys.argv [1:])
options.query verrà quindi impostato sul valore passato allo script.
Si crea un parser semplicemente facendo
parser = optparse.OptionParser()
Queste sono tutte le basi di cui hai bisogno. Ecco uno script Python completo che mostra questo:
import optparse
parser = optparse.OptionParser()
parser.add_option('-q', '--query',
action="store", dest="query",
help="query string", default="spam")
options, args = parser.parse_args()
print 'Query string:', options.query
5 linee di pitone che ti mostrano le basi.
Salvalo in sample.py ed eseguilo una volta con
python sample.py
e una volta con
python sample.py --query myquery
Oltre a ciò, scoprirai che optparse è molto facile da estendere. In uno dei miei progetti, ho creato una classe Command che consente di nidificare facilmente i sottocomandi in un albero dei comandi. Usa optparse pesantemente per concatenare i comandi insieme. Non è qualcosa che posso facilmente spiegare in poche righe, ma sentiti libero di navigare nel mio repository per la classe principale, così come una classe che la usa e il parser di opzioni
-mcProfile -o program.prof
ma agrparcer sta catturando questi argomenti, come posso passare questi argomenti a python exe ???
argparse
è la strada da percorrere. Ecco un breve riassunto di come usarlo:
1) Inizializza
import argparse
# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')
2) Aggiungi argomenti
# Required positional argument
parser.add_argument('pos_arg', type=int,
help='A required integer positional argument')
# Optional positional argument
parser.add_argument('opt_pos_arg', type=int, nargs='?',
help='An optional integer positional argument')
# Optional argument
parser.add_argument('--opt_arg', type=int,
help='An optional integer argument')
# Switch
parser.add_argument('--switch', action='store_true',
help='A boolean switch')
3) Parse
args = parser.parse_args()
4) Accesso
print("Argument values:")
print(args.pos_arg)
print(args.opt_pos_arg)
print(args.opt_arg)
print(args.switch)
5) Controllare i valori
if args.pos_arg > 10:
parser.error("pos_arg cannot be larger than 10")
Uso corretto:
$ ./app 1 2 --opt_arg 3 --switch
Argument values:
1
2
3
True
Argomenti errati:
$ ./app foo 2 --opt_arg 3 --switch
usage: convert [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
app: error: argument pos_arg: invalid int value: 'foo'
$ ./app 11 2 --opt_arg 3
Argument values:
11
2
3
False
usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
convert: error: pos_arg cannot be larger than 10
Aiuto completo:
$ ./app -h
usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
Optional app description
positional arguments:
pos_arg A required integer positional argument
opt_pos_arg An optional integer positional argument
optional arguments:
-h, --help show this help message and exit
--opt_arg OPT_ARG An optional integer argument
--switch A boolean switch
Dal 2012 v'è una molto semplice, potente e davvero fresco modulo per argomento l'analisi chiamato docopt . Ecco un esempio tratto dalla sua documentazione:
"""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)
Quindi è così: 2 righe di codice più la tua stringa doc che è essenziale e ottieni gli argomenti analizzati e disponibili nell'oggetto argomenti.
Dal 2017 c'è un altro fantastico modulo chiamato python-fire . Può generare un'interfaccia CLI per il tuo codice eseguendo l' analisi dell'argomento zero . Ecco un semplice esempio dalla documentazione (questo piccolo programma espone la funzione double
alla riga di comando):
import fire
class Calculator(object):
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
Dalla riga di comando, puoi eseguire:
> calculator.py double 10
20
> calculator.py double --number=15
30
Il nuovo modo alla moda è argparse
per questi motivi. argparse> optparse> getopt
aggiornamento: a partire da py2.7 argparse fa parte della libreria standard e optparse è obsoleto.
Preferisco fare clic . Estrae le opzioni di gestione e permette "(...) di creare bellissime interfacce da riga di comando in modo compostabile con il minimo codice necessario".
Ecco un esempio di utilizzo:
import click
@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
help='The person to greet.')
def hello(count, name):
"""Simple program that greets NAME for a total of COUNT times."""
for x in range(count):
click.echo('Hello %s!' % name)
if __name__ == '__main__':
hello()
Inoltre genera automaticamente pagine di aiuto ben formattate:
$ python hello.py --help
Usage: hello.py [OPTIONS]
Simple program that greets NAME for a total of COUNT times.
Options:
--count INTEGER Number of greetings.
--name TEXT The person to greet.
--help Show this message and exit.
Praticamente tutti usano getopt
Ecco il codice di esempio per il documento:
import getopt, sys
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
except getopt.GetoptError:
# print help information and exit:
usage()
sys.exit(2)
output = None
verbose = False
for o, a in opts:
if o == "-v":
verbose = True
if o in ("-h", "--help"):
usage()
sys.exit()
if o in ("-o", "--output"):
output = a
Quindi, in una parola, ecco come funziona.
Hai due tipi di opzioni. Coloro che stanno ricevendo argomenti e quelli che sono come interruttori.
sys.argv
è praticamente tuo char** argv
in C. Come in C salti il primo elemento che è il nome del tuo programma e analizzi solo gli argomenti:sys.argv[1:]
Getopt.getopt
lo analizzerà secondo la regola che dai nell'argomento.
"ho:v"
qui descrive le brevi argomenti: -ONELETTER
. Il :
mezzo che -o
accetta un argomento.
["help", "output="]
Descrive infine argomenti lunghi ( --MORETHANONELETTER
). L' =
output after indica ancora una volta che l'output accetta un argomento.
Il risultato è un elenco di coppie (opzione, argomento)
Se un'opzione non accetta alcun argomento (come --help
qui) la arg
parte è una stringa vuota. Di solito, quindi, si desidera eseguire il ciclo su questo elenco e testare il nome dell'opzione come nell'esempio.
Spero che questo ti abbia aiutato.
getopt
nelle versioni più recenti di Python questa risposta non è più aggiornata.
getopt
è ancora deprecato ... Ma la sua documentazione afferma che è principalmente fornita agli utenti che hanno familiarità con la getopt()
funzione C , e riconosce che per gli altri utenti argparse
potrebbe essere una soluzione migliore, che consente di "scrivere meno codice e ottenere migliore aiuto e messaggi di errore ".
Utilizzare ciò optparse
che viene fornito con la libreria standard. Per esempio:
#!/usr/bin/env python
import optparse
def main():
p = optparse.OptionParser()
p.add_option('--person', '-p', default="world")
options, arguments = p.parse_args()
print 'Hello %s' % options.person
if __name__ == '__main__':
main()
Fonte: utilizzo di Python per creare strumenti da riga di comando UNIX
Tuttavia a partire da Python 2.7 optparse è obsoleto, vedi: Perché usare argparse anziché optparse?
Nel caso in cui potrebbe essere necessario, questo può aiutare se avete bisogno di afferrare gli argomenti Unicode su Win32 (2k, XP, ecc):
from ctypes import *
def wmain(argc, argv):
print argc
for i in argv:
print i
return 0
def startup():
size = c_int()
ptr = windll.shell32.CommandLineToArgvW(windll.kernel32.GetCommandLineW(), byref(size))
ref = c_wchar_p * size.value
raw = ref.from_address(ptr)
args = [arg for arg in raw]
windll.kernel32.LocalFree(ptr)
exit(wmain(len(args), args))
startup()
Valori predefiniti dell'argomento della riga di comando
Sebbene argparse
sia eccezionale ed è la risposta giusta per opzioni della riga di comando completamente documentate e funzionalità avanzate, è possibile utilizzare le impostazioni predefinite degli argomenti delle funzioni per gestire gli argomenti posizionali in modo molto semplice.
import sys
def get_args(name='default', first='a', second=2):
return first, int(second)
first, second = get_args(*sys.argv)
print first, second
L'argomento 'name' acquisisce il nome dello script e non viene utilizzato. L'output del test è simile al seguente:
> ./test.py
a 2
> ./test.py A
A 2
> ./test.py A 20
A 20
Per gli script semplici in cui desidero solo alcuni valori predefiniti, lo trovo abbastanza sufficiente. Potresti anche voler includere un certo tipo di coercizione nei valori di ritorno o i valori della riga di comando saranno tutti stringhe.
Preferisco optparse a getopt. È molto dichiarativo: gli dici i nomi delle opzioni e gli effetti che dovrebbero avere (ad esempio, l'impostazione di un campo booleano) e ti restituisce un dizionario popolato in base alle tue specifiche.
Penso che il modo migliore per progetti più grandi sia optparse, ma se stai cercando un modo semplice, forse http://werkzeug.pocoo.org/documentation/script è qualcosa per te.
from werkzeug import script
# actions go here
def action_foo(name=""):
"""action foo does foo"""
pass
def action_bar(id=0, title="default title"):
"""action bar does bar"""
pass
if __name__ == '__main__':
script.run()
Quindi praticamente ogni funzione action_ * è esposta alla riga di comando e un bel messaggio di aiuto viene generato gratuitamente.
python foo.py
usage: foo.py <action> [<options>]
foo.py --help
actions:
bar:
action bar does bar
--id integer 0
--title string default title
foo:
action foo does foo
--name string
declarative_parser
. Naturalmente, se si sta lavorando con werkzeug, potrebbe essere meglio mantenere il werkzung.script
. Ad ogni modo, sono un grande fan di tale approccio.
Il codice Argparse può essere più lungo del codice di implementazione reale!
Questo è un problema che trovo con le opzioni di analisi degli argomenti più popolari è che se i tuoi parametri sono solo modesti, il codice per documentarli diventa sproporzionatamente grande a vantaggio che offrono.
Un nuovo arrivato relativamente all'argomento che analizza la scena (penso) è plac .
Effettua alcuni compromessi riconosciuti con argparse, ma utilizza la documentazione in linea e si avvolge semplicemente attorno alla main()
funzione di tipo funzione:
def main(excel_file_path: "Path to input training file.",
excel_sheet_name:"Name of the excel sheet containing training data including columns 'Label' and 'Description'.",
existing_model_path: "Path to an existing model to refine."=None,
batch_size_start: "The smallest size of any minibatch."=10.,
batch_size_stop: "The largest size of any minibatch."=250.,
batch_size_step: "The step for increase in minibatch size."=1.002,
batch_test_steps: "Flag. If True, show minibatch steps."=False):
"Train a Spacy (http://spacy.io/) text classification model with gold document and label data until the model nears convergence (LOSS < 0.5)."
pass # Implementation code goes here!
if __name__ == '__main__':
import plac; plac.call(main)
consoleargs merita di essere menzionato qui. È molto facile da usare Controlla:
from consoleargs import command
@command
def main(url, name=None):
"""
:param url: Remote URL
:param name: File name
"""
print """Downloading url '%r' into file '%r'""" % (url, name)
if __name__ == '__main__':
main()
Ora in console:
% python demo.py --help
Usage: demo.py URL [OPTIONS]
URL: Remote URL
Options:
--name -n File name
% python demo.py http://www.google.com/
Downloading url ''http://www.google.com/'' into file 'None'
% python demo.py http://www.google.com/ --name=index.html
Downloading url ''http://www.google.com/'' into file ''index.html''
Ecco un metodo, non una libreria, che sembra funzionare per me.
Gli obiettivi qui sono di essere concisi, ogni argomento analizzato da una singola riga, gli arg lineini per la leggibilità, il codice è semplice e non dipende da alcun modulo speciale (solo os + sys), avverte con grazia di argomenti mancanti o sconosciuti , usa un semplice ciclo per / range () e funziona su python 2.xe 3.x
Sono mostrati due flag di commutazione (-d, -v) e due valori controllati da argomenti (-i xxx e -o xxx).
import os,sys
def HelpAndExit():
print("<<your help output goes here>>")
sys.exit(1)
def Fatal(msg):
sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))
sys.exit(1)
def NextArg(i):
'''Return the next command line argument (if there is one)'''
if ((i+1) >= len(sys.argv)):
Fatal("'%s' expected an argument" % sys.argv[i])
return(1, sys.argv[i+1])
### MAIN
if __name__=='__main__':
verbose = 0
debug = 0
infile = "infile"
outfile = "outfile"
# Parse command line
skip = 0
for i in range(1, len(sys.argv)):
if not skip:
if sys.argv[i][:2] == "-d": debug ^= 1
elif sys.argv[i][:2] == "-v": verbose ^= 1
elif sys.argv[i][:2] == "-i": (skip,infile) = NextArg(i)
elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
elif sys.argv[i][:2] == "-h": HelpAndExit()
elif sys.argv[i][:1] == "-": Fatal("'%s' unknown argument" % sys.argv[i])
else: Fatal("'%s' unexpected" % sys.argv[i])
else: skip = 0
print("%d,%d,%s,%s" % (debug,verbose,infile,outfile))
L'obiettivo di NextArg () è quello di restituire l'argomento successivo durante la ricerca di dati mancanti e 'skip' salta il ciclo quando si utilizza NextArg (), mantenendo il flag analizzato fino a una riga.
Ho esteso l'approccio di Erco per consentire gli argomenti posizionali richiesti e gli argomenti opzionali. Questi dovrebbero precedere gli argomenti -d, -v ecc.
Argomenti posizionali e opzionali possono essere recuperati rispettivamente con PosArg (i) e OptArg (i, default). Quando viene trovato un argomento facoltativo, la posizione iniziale della ricerca di opzioni (ad es. -I) viene spostata 1 in avanti per evitare di causare un fatale "imprevisto".
import os,sys
def HelpAndExit():
print("<<your help output goes here>>")
sys.exit(1)
def Fatal(msg):
sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))
sys.exit(1)
def NextArg(i):
'''Return the next command line argument (if there is one)'''
if ((i+1) >= len(sys.argv)):
Fatal("'%s' expected an argument" % sys.argv[i])
return(1, sys.argv[i+1])
def PosArg(i):
'''Return positional argument'''
if i >= len(sys.argv):
Fatal("'%s' expected an argument" % sys.argv[i])
return sys.argv[i]
def OptArg(i, default):
'''Return optional argument (if there is one)'''
if i >= len(sys.argv):
Fatal("'%s' expected an argument" % sys.argv[i])
if sys.argv[i][:1] != '-':
return True, sys.argv[i]
else:
return False, default
### MAIN
if __name__=='__main__':
verbose = 0
debug = 0
infile = "infile"
outfile = "outfile"
options_start = 3
# --- Parse two positional parameters ---
n1 = int(PosArg(1))
n2 = int(PosArg(2))
# --- Parse an optional parameters ---
present, a3 = OptArg(3,50)
n3 = int(a3)
options_start += int(present)
# --- Parse rest of command line ---
skip = 0
for i in range(options_start, len(sys.argv)):
if not skip:
if sys.argv[i][:2] == "-d": debug ^= 1
elif sys.argv[i][:2] == "-v": verbose ^= 1
elif sys.argv[i][:2] == "-i": (skip,infile) = NextArg(i)
elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
elif sys.argv[i][:2] == "-h": HelpAndExit()
elif sys.argv[i][:1] == "-": Fatal("'%s' unknown argument" % sys.argv[i])
else: Fatal("'%s' unexpected" % sys.argv[i])
else: skip = 0
print("Number 1 = %d" % n1)
print("Number 2 = %d" % n2)
print("Number 3 = %d" % n3)
print("Debug = %d" % debug)
print("verbose = %d" % verbose)
print("infile = %s" % infile)
print("outfile = %s" % outfile)