Antworten:
Diese Antwort schlägt vor, optparse
welche für ältere Python-Versionen geeignet ist. Für Python 2.7 und höher, argparse
ersetzt optparse
. Weitere Informationen finden Sie in dieser Antwort .
Wie andere Leute betonten, ist es besser, mit optparse über getopt zu gehen. getopt ist so ziemlich eine Eins-zu-Eins-Zuordnung der Standardfunktionen der getopt (3) C-Bibliothek und nicht sehr einfach zu bedienen.
optparse ist zwar etwas ausführlicher, aber viel besser strukturiert und später einfacher zu erweitern.
Hier ist eine typische Zeile, um Ihrem Parser eine Option hinzuzufügen:
parser.add_option('-q', '--query',
action="store", dest="query",
help="query string", default="spam")
Es spricht so ziemlich für sich selbst; Zur Verarbeitungszeit akzeptiert es -q oder --query als Optionen, speichert das Argument in einem Attribut namens query und hat einen Standardwert, wenn Sie ihn nicht angeben. Es ist auch selbstdokumentierend, dass Sie das Hilfeargument (das bei Ausführung mit -h / - help verwendet wird) genau dort mit der Option deklarieren.
Normalerweise analysieren Sie Ihre Argumente mit:
options, args = parser.parse_args()
Dadurch werden standardmäßig die an das Skript übergebenen Standardargumente analysiert (sys.argv [1:]).
options.query wird dann auf den Wert gesetzt, den Sie an das Skript übergeben haben.
Sie erstellen einen Parser einfach dadurch
parser = optparse.OptionParser()
Dies sind alle Grundlagen, die Sie benötigen. Hier ist ein vollständiges Python-Skript, das dies zeigt:
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 Python-Zeilen, die Ihnen die Grundlagen zeigen.
Speichern Sie es in sample.py und führen Sie es einmal mit aus
python sample.py
und einmal mit
python sample.py --query myquery
Darüber hinaus werden Sie feststellen, dass Optparse sehr einfach zu erweitern ist. In einem meiner Projekte habe ich eine Befehlsklasse erstellt, mit der Sie Unterbefehle einfach in einem Befehlsbaum verschachteln können. Optparse wird häufig verwendet, um Befehle miteinander zu verketten. Es ist nicht einfach in ein paar Zeilen zu erklären, aber Sie können in meinem Repository nach der Hauptklasse sowie einer Klasse, die sie verwendet, und dem Optionsparser suchen
-mcProfile -o program.prof
aber agrparcer erfasst diese Argumente. Wie übergebe ich diese Argumente an Python Exe?
argparse
ist der Weg zu gehen. Hier ist eine kurze Zusammenfassung der Verwendung:
1) Initialisieren
import argparse
# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')
2) Argumente hinzufügen
# 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) Analysieren
args = parser.parse_args()
4) Zugang
print("Argument values:")
print(args.pos_arg)
print(args.opt_pos_arg)
print(args.opt_arg)
print(args.switch)
5) Prüfwerte
if args.pos_arg > 10:
parser.error("pos_arg cannot be larger than 10")
Richtige Verwendung:
$ ./app 1 2 --opt_arg 3 --switch
Argument values:
1
2
3
True
Falsche Argumente:
$ ./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
Volle Hilfe:
$ ./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
Seit 2012 gibt es ein sehr einfaches, leistungsstarkes und wirklich cooles Modul zum Parsen von Argumenten namens docopt . Hier ist ein Beispiel aus der Dokumentation:
"""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)
Das ist es also: 2 Zeilen Code plus Ihre doc String, ist wesentlich und Sie erhalten Ihre Argumente in Ihren Argumenten Objekt analysiert und zur Verfügung.
Seit 2017 gibt es ein weiteres cooles Modul namens Python-Fire . Es kann eine CLI-Schnittstelle für Ihren Code generieren, während Sie keine Argumente analysieren. Hier ist ein einfaches Beispiel aus der Dokumentation (dieses kleine Programm stellt die Funktion double
der Befehlszeile zur Verfügung):
import fire
class Calculator(object):
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
Über die Befehlszeile können Sie Folgendes ausführen:
> calculator.py double 10
20
> calculator.py double --number=15
30
Der neue Hüftweg ist argparse
aus diesen Gründen. argparse> optparse> getopt
Update: Ab py2.7 ist argparse Teil der Standardbibliothek und optparse ist veraltet.
Ich bevorzuge Click . Es abstrahiert Verwaltungsoptionen und ermöglicht "(...) das Erstellen schöner Befehlszeilenschnittstellen auf komponierbare Weise mit so wenig Code wie nötig".
Hier ist ein Beispiel für die Verwendung:
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()
Außerdem werden automatisch gut formatierte Hilfeseiten generiert:
$ 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.
So ziemlich jeder benutzt getopt
Hier ist der Beispielcode für das Dokument:
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
Mit einem Wort, hier ist, wie es funktioniert.
Sie haben zwei Arten von Optionen. Diejenigen, die Argumente erhalten, und diejenigen, die wie Schalter sind.
sys.argv
ist so ziemlich Ihr char** argv
in C. Wie in C überspringen Sie das erste Element, das der Name Ihres Programms ist, und analysieren nur die Argumente:sys.argv[1:]
Getopt.getopt
analysiert es gemäß der Regel, die Sie im Argument angeben.
"ho:v"
Hier werden die kurzen Argumente beschrieben : -ONELETTER
. Das :
bedeutet das-o
ein Argument akzeptiert wird.
Schließlich ["help", "output="]
lange Argumente beschreibt ( --MORETHANONELETTER
). Das=
After-Ausgabe bedeutet erneut, dass die Ausgabe ein Argument akzeptiert.
Das Ergebnis ist eine Liste von Paaren (Option, Argument)
Wenn eine Option kein Argument akzeptiert (wie --help
hier), ist das arg
Teil eine leere Zeichenfolge. In der Regel möchten Sie dann diese Liste durchlaufen und den Optionsnamen wie im Beispiel testen.
Ich hoffe das hat dir geholfen.
getopt
in neueren Versionen von Python ist diese Antwort veraltet.
getopt
ist es immer noch nicht veraltet ... In der Dokumentation heißt es jedoch, dass es hauptsächlich für Benutzer bereitgestellt wird, die mit der C- getopt()
Funktion vertraut sind , und dass andere Benutzer argparse
möglicherweise eine bessere Lösung sind, um "weniger Code schreiben und abrufen zu können" bessere Hilfe und Fehlermeldungen ".
Verwendung, optparse
die mit der Standardbibliothek geliefert wird. Beispielsweise:
#!/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()
Quelle: Verwenden von Python zum Erstellen von UNIX-Befehlszeilentools
Ab Python 2.7 ist optparse jedoch veraltet. Weitere Informationen finden Sie unter: Warum argparse anstelle von optparse verwenden?
Für den Fall , müssen Sie möglicherweise auf, das helfen kann , wenn Sie benötigen greifen Unicode - Argumente auf Win32 (2K, XP etc.):
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()
Die Standardeinstellungen für Lightweight-Befehlszeilenargumente
Obwohl argparse
es großartig ist und die richtige Antwort für vollständig dokumentierte Befehlszeilenoptionen und erweiterte Funktionen ist, können Sie die Standardeinstellungen für Funktionsargumente verwenden, um einfache Positionsargumente sehr einfach zu handhaben.
import sys
def get_args(name='default', first='a', second=2):
return first, int(second)
first, second = get_args(*sys.argv)
print first, second
Das Argument 'name' erfasst den Skriptnamen und wird nicht verwendet. Die Testausgabe sieht folgendermaßen aus:
> ./test.py
a 2
> ./test.py A
A 2
> ./test.py A 20
A 20
Für einfache Skripte, bei denen ich nur einige Standardwerte möchte, finde ich dies völlig ausreichend. Möglicherweise möchten Sie auch einen Typzwang in die Rückgabewerte aufnehmen, oder Befehlszeilenwerte sind alle Zeichenfolgen.
Ich bevorzuge optparse gegenüber getopt. Es ist sehr aussagekräftig: Sie geben die Namen der Optionen und die Auswirkungen an, die sie haben sollten (z. B. Festlegen eines Booleschen Felds), und Sie erhalten ein Wörterbuch zurück, das gemäß Ihren Spezifikationen gefüllt ist.
Ich denke, der beste Weg für größere Projekte ist optparse, aber wenn Sie nach einem einfachen Weg suchen, ist http://werkzeug.pocoo.org/documentation/script vielleicht etwas für Sie.
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()
Grundsätzlich ist also jede Funktion action_ * der Befehlszeile ausgesetzt und eine nette Hilfemeldung wird kostenlos generiert.
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
. Wenn man mit werkzeug arbeitet, ist es natürlich besser, das zu behalten werkzung.script
. Wie auch immer, ich bin ein großer Fan eines solchen Ansatzes.
Argparse-Code kann länger sein als der tatsächliche Implementierungscode!
Das ist ein Problem, das ich bei den meisten gängigen Optionen zum Parsen von Argumenten finde: Wenn Ihre Parameter nur bescheiden sind, wird der Code, um sie zu dokumentieren, zum Nutzen, den sie bieten, unverhältnismäßig groß.
Ein relativer Neuling in der Argument-Parsing-Szene (glaube ich) ist plac .
Es macht einige anerkannte Kompromisse mit Argparse, verwendet jedoch Inline-Dokumentation und umschließt einfach die Typfunktionsfunktion main()
:
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 verdient es, hier erwähnt zu werden. Es ist sehr einfach zu bedienen. Hör zu:
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()
Jetzt in der Konsole:
% 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''
Hier ist eine Methode, keine Bibliothek, die für mich zu funktionieren scheint.
Die Ziele hier sind knapp zu sein, jedes Argument wird durch eine einzelne Zeile analysiert, die Argumente werden zur besseren Lesbarkeit angezeigt, der Code ist einfach und hängt nicht von speziellen Modulen ab (nur os + sys), warnt vor fehlenden oder unbekannten Argumenten Verwenden Sie eine einfache for / range () -Schleife und arbeiten Sie mit Python 2.x und 3.x.
Dargestellt sind zwei Umschaltflags (-d, -v) und zwei durch Argumente gesteuerte Werte (-i xxx und -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))
Das Ziel von NextArg () ist es, das nächste Argument zurückzugeben, während nach fehlenden Daten gesucht wird, und 'überspringen' die Schleife zu überspringen, wenn NextArg () verwendet wird, wobei das Flag auf einen Liner reduziert wird.
Ich habe den Ansatz von Erco erweitert, um erforderliche Positionsargumente und optionale Argumente zu berücksichtigen. Diese sollten vor den Argumenten -d, -v usw. stehen.
Positions- und optionale Argumente können mit PosArg (i) bzw. OptArg (i, Standard) abgerufen werden. Wenn ein optionales Argument gefunden wird, wird die Startposition für die Suche nach Optionen (z. B. -i) um 1 nach vorne verschoben, um zu vermeiden, dass ein "unerwarteter" Todesfall auftritt.
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)