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__)


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow