Python Language
Analysera kommandoradsargument
Sök…
Introduktion
De flesta kommandoradsverktyg förlitar sig på argument som skickats till programmet vid dess körning. Istället för att be om inmatning förväntar sig dessa program att data eller specifika flaggor (som blir booleaner) ska ställas in. Detta gör att både användaren och andra program kan köra Python-filen som skickar data när den startar. Det här avsnittet förklarar och demonstrerar implementeringen och användningen av kommandoradsargument i Python.
Hej värld i argparse
Följande program säger hej till användaren. Det krävs ett positionsargument, användarens namn och kan också berättas om hälsningen.
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 mer information, läs den argparse dokumentationen .
Grundläggande exempel med docopt
docopt vänder kommandoradsargumentet att analysera på huvudet. Istället för att analysera argumenten skriver du bara användningssträngen för ditt program och docoptar användarsträngen och använder den för att extrahera kommandoradsargumenten.
"""
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)
Provkörningar:
$ 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'}
Ställa in ömsesidigt exklusiva argument med argparse
Om du vill att två eller flera argument ska vara ömsesidigt exklusiva. Du kan använda funktionen argparse.ArgumentParser.add_mutually_exclusive_group()
. I exemplet nedan kan antingen foo eller bar existera men inte båda samtidigt.
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
Om du försöker köra skriptet som anger både --foo
och --bar
argumenter klagar skriptet med meddelandet nedan.
error: argument -b/--bar: not allowed with argument -f/--foo
Använda kommandoradsargument med argv
Närhelst ett Python-skript anropas från kommandoraden kan användaren leverera ytterligare kommandoradsargument som kommer att vidarebefordras till skriptet. Dessa argument kommer att vara tillgängliga för programmeraren från systemvariabeln sys.argv
("argv" är ett traditionellt namn som används i de flesta programmeringsspråk, och det betyder " arg ument v ector").
I överensstämmelse är det första elementet i sys.argv
listan namnet på själva Python-skriptet, medan resten av elementen är de token som passeras av användaren när de åberopar skriptet.
# 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']
Här är ytterligare ett exempel på hur du använder argv
. Vi avlägsnar först det ursprungliga elementet i sys.argv eftersom det innehåller skriptets namn. Sedan kombinerar vi resten av argumenten i en enda mening och skriver slutligen ut den meningen som förbereder namnet på den för närvarande inloggade användaren (så att den emulerar ett chattprogram).
import getpass
import sys
words = sys.argv[1:]
sentence = " ".join(words)
print("[%s] %s" % (getpass.getuser(), sentence))
Den algoritm som vanligtvis används när "manuellt" analyserar ett antal icke-positionella argument är att iterera över listan sys.argv
. Ett sätt är att gå över listan och poppa varje element i den:
# 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()
Anpassat parser-felmeddelande med argparse
Du kan skapa parser-felmeddelanden enligt dina skriptbehov. Detta argparse.ArgumentParser.error
funktionen argparse.ArgumentParser.error
. Exemplet nedan visar skriptet som skriver ut en användning och ett felmeddelande till stderr
när --foo
ges men inte - --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
Antar att ditt skriptnamn är sample.py, och vi kör: python sample.py --foo ds_in_fridge
Skriptet kommer att klaga med följande:
usage: sample.py [-h] [-f FOO] [-b BAR]
sample.py: error: --foo requires --bar. You did not specify bar.
Konceptuell gruppering av argument med argparse.add_argument_group ()
När du skapar ett argparse ArgumentParser () och kör ditt program med '-h' får du ett automatiserat användningsmeddelande som förklarar vilka argument du kan köra din programvara med. Som standard är positioneringsargument och villkorade argument uppdelade i två kategorier, till exempel är här ett litet skript (exempel.py) och utdata när du kör 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
Det finns vissa situationer där du vill dela dina argument i ytterligare konceptuella avsnitt för att hjälpa din användare. Till exempel kanske du vill ha alla inmatningsalternativ i en grupp och alla utgångsformeringsalternativ i en annan. Exemplet ovan kan justeras för att separera --foo_*
args från --bar_*
args som så.
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()
Vilket producerar denna utgång när python example.py -h
körs:
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
Avancerat exempel med docopt och docopt_dispatch
Som med docopt, med [docopt_dispatch] du hantverk din --help
i __doc__
variabel din ingångspunkt modul. Där kallar du dispatch
med doc-strängen som argument, så att den kan köra parsern över den.
Detta görs, istället för att manuellt hantera argumenten (som vanligtvis hamnar i en hög cyklomatisk om / annars-struktur), lämnar du det att skickas och ger bara hur du vill hantera uppsättningen av argument.
Detta är vad dispatch.on
dekoratören är avsedd för: du ger det argumentet eller sekvensen av argument som ska utlösa funktionen, och den funktionen kommer att köras med matchande värden som parametrar.
"""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__)