Python Language
Befehlszeilenargumente analysieren
Suche…
Einführung
Die meisten Befehlszeilentools sind auf Argumente angewiesen, die bei der Ausführung an das Programm übergeben werden. Anstatt zur Eingabe aufzufordern, erwarten diese Programme, dass Daten oder bestimmte Flags (die zu Booleans werden) gesetzt werden. Dies ermöglicht es dem Benutzer und anderen Programmen, die Python-Datei auszuführen, wobei die Daten beim Start übergeben werden. In diesem Abschnitt wird die Implementierung und Verwendung von Befehlszeilenargumenten in Python erläutert und veranschaulicht.
Hallo Welt in Schwierigkeiten
Das folgende Programm sagt dem Benutzer Hallo. Es erfordert ein Positionsargument, den Namen des Benutzers, und die Begrüßung kann auch mitgeteilt werden.
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!
Für weitere Details lesen Sie bitte die argparse-Dokumentation .
Grundlegendes Beispiel mit docopt
docopt konvertiert Befehlszeilenargumente auf den Kopf. Statt die Argumente zu analysieren, schreiben Sie einfach die Verwendungszeichenfolge für Ihr Programm, und docopt analysiert die Verwendungszeichenfolge und verwendet sie zum Extrahieren der Befehlszeilenargumente.
"""
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)
Probeläufe:
$ 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'}
Setzen Sie sich gegenseitig ausschließende Argumente mit argparse
Wenn zwei oder mehr Argumente sich gegenseitig ausschließen sollen. Sie können die Funktion argparse.ArgumentParser.add_mutually_exclusive_group()
. Im folgenden Beispiel können entweder foo oder bar vorhanden sein, jedoch nicht beide gleichzeitig.
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
Wenn Sie versuchen, das Skript --foo
--bar
Argumente --foo
und --bar
, beschwert sich das Skript mit der folgenden Meldung.
error: argument -b/--bar: not allowed with argument -f/--foo
Befehlszeilenargumente mit argv verwenden
Wenn ein Python-Skript von der Befehlszeile aus aufgerufen wird, kann der Benutzer zusätzliche Befehlszeilenargumente angeben, die an das Skript übergeben werden. Diese Argumente werden an den Programmierer von der Systemvariablen zur Verfügung sys.argv
( „argv“ ist ein traditioneller Name in den meisten Programmiersprachen verwendet, und es bedeutet „arg UMENT v ector“).
sys.argv
ist das erste Element in der Liste sys.argv
der Name des Python-Skripts selbst, während die übrigen Elemente die Token sind, die der Benutzer beim Aufrufen des Skripts sys.argv
.
# 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']
Hier ist ein weiteres Beispiel für die Verwendung von argv
. Wir entfernen zunächst das ursprüngliche Element von sys.argv, da es den Namen des Skripts enthält. Dann kombinieren wir den Rest der Argumente in einem einzigen Satz und drucken diesen Satz vor dem Namen des aktuell angemeldeten Benutzers (damit ein Chat-Programm emuliert wird).
import getpass
import sys
words = sys.argv[1:]
sentence = " ".join(words)
print("[%s] %s" % (getpass.getuser(), sentence))
Der Algorithmus, der häufig verwendet wird, wenn eine Anzahl nicht-positioneller Argumente "manuell" analysiert wird, besteht darin, die Liste sys.argv
. Eine Möglichkeit ist, die Liste durchzugehen und jedes Element davon zu platzieren:
# 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()
Benutzerdefinierte Parser-Fehlernachricht mit Argumenten
Sie können Parser-Fehlermeldungen entsprechend Ihren Skriptanforderungen erstellen. Dies geschieht über die Funktion argparse.ArgumentParser.error
. Das folgende Beispiel zeigt, dass das Skript eine Verwendung und eine --foo
an stderr
--foo
wenn --foo
wird, aber nicht --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
Angenommen, Ihr Skriptname lautet sample.py, und wir führen python sample.py --foo ds_in_fridge
: python sample.py --foo ds_in_fridge
Das Skript wird sich mit folgendem beschweren:
usage: sample.py [-h] [-f FOO] [-b BAR]
sample.py: error: --foo requires --bar. You did not specify bar.
Konzeptionelle Gruppierung von Argumenten mit argparse.add_argument_group ()
Wenn Sie argparse ArgumentParser () erstellen und Ihr Programm mit '-h' ausführen, erhalten Sie eine automatisierte Verwendungsnachricht, in der erläutert wird, mit welchen Argumenten Sie Ihre Software ausführen können. Positionsargumente und bedingte Argumente sind standardmäßig in zwei Kategorien unterteilt. Beispiel: Ein kleines Skript (example.py) und die Ausgabe, wenn Sie python example.py -h
ausführen.
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
Es gibt Situationen, in denen Sie Ihre Argumente in weitere konzeptionelle Abschnitte unterteilen möchten, um Ihren Benutzer zu unterstützen. Beispielsweise möchten Sie möglicherweise alle Eingabeoptionen in einer Gruppe und alle Optionen zur Ausgabeformatierung in einer anderen Gruppe haben. Das obige Beispiel kann angepasst werden, um die --foo_*
args von den --bar_*
args zu trennen.
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()
Was erzeugt diese Ausgabe, wenn python example.py -h
wird:
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
Erweitertes Beispiel mit docopt und docopt_dispatch
Wie bei docopt bilden Sie mit [docopt_dispatch] Ihre --help
in die Variable __doc__
Ihres Einstiegspunktmoduls. Dort rufen Sie dispatch
mit dem doc-String als Argument auf, damit der Parser darüber laufen kann.
Anstatt die Argumente manuell zu handhaben (was normalerweise in einer if / else-Struktur mit hoher Zyklizität endet), überlassen Sie es dem Versand, indem Sie nur angeben, wie Sie die Menge der Argumente behandeln wollen.
Dafür gibt es den dispatch.on
Dekorator: Sie geben ihm das Argument oder die Folge von Argumenten, die die Funktion auslösen sollen, und diese Funktion wird mit den übereinstimmenden Werten als Parameter ausgeführt.
"""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__)