Szukaj…


Wprowadzenie

Większość narzędzi wiersza poleceń opiera się na argumentach przekazywanych do programu po jego uruchomieniu. Zamiast monitować o wprowadzenie, programy te oczekują ustawienia danych lub określonych flag (które stają się logicznymi). Dzięki temu zarówno użytkownik, jak i inne programy mogą uruchomić plik Python, przekazując mu dane podczas uruchamiania. Ta sekcja wyjaśnia i demonstruje implementację i użycie argumentów wiersza poleceń w Pythonie.

Witaj świecie w argparse

Poniższy program wita użytkownika. Wymaga jednego argumentu pozycyjnego, nazwy użytkownika, i można go również powitać.

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!

Aby uzyskać więcej informacji, przeczytaj dokumentację argparse .

Podstawowy przykład z docopt

docopt obraca analizę argumentów wiersza poleceń na głowie. Zamiast analizować argumenty, wystarczy napisać ciąg użycia dla programu, a docopt analizuje ciąg użycia i używa go do wyodrębnienia argumentów wiersza poleceń.

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

Przykładowe przebiegi:

$ 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'}

Ustalanie wykluczających się argumentów za pomocą argparse

Jeśli chcesz, aby dwa lub więcej argumentów wykluczały się wzajemnie. Możesz użyć funkcji argparse.ArgumentParser.add_mutually_exclusive_group() . W poniższym przykładzie może istnieć zarówno foo, jak i pasek, ale nie oba jednocześnie.

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

Jeśli próbujesz uruchomić skrypt określający zarówno --foo i --bar argumenty, skrypt skarżą się z poniższym komunikatem.

error: argument -b/--bar: not allowed with argument -f/--foo

Używanie argumentów wiersza poleceń z argv

Ilekroć skrypt Python jest wywoływany z wiersza poleceń, użytkownik może podać dodatkowe argumenty wiersza poleceń, które zostaną przekazane do skryptu. Argumenty te będą dostępne dla programisty od zmiennej systemowej sys.argv ( „argv” to tradycyjna nazwa używana w większości języków programowania, a to oznacza „arg ument v ector”).

Zgodnie z konwencją pierwszym elementem na liście sys.argv jest nazwa samego skryptu Python, a pozostałe elementy to tokeny przekazywane przez użytkownika podczas wywoływania skryptu.

# 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']

Oto kolejny przykład użycia argv . Najpierw usuwamy początkowy element pliku sys.argv, ponieważ zawiera on nazwę skryptu. Następnie łączymy pozostałe argumenty w jedno zdanie, a na końcu drukujemy to zdanie, poprzedzając nazwę aktualnie zalogowanego użytkownika (tak, aby emulował program czatu).

import getpass
import sys

words = sys.argv[1:]
sentence = " ".join(words)
print("[%s] %s" % (getpass.getuser(), sentence))

Algorytmem powszechnie stosowanym podczas „ręcznego” analizowania wielu argumentów pozycyjnych jest iteracja po liście sys.argv . Jednym ze sposobów jest przejrzenie listy i usunięcie każdego jej elementu:

# 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()

Komunikat o błędzie niestandardowego analizatora składni z argumentem argparse

Można tworzyć komunikaty o błędach analizatora składni zgodnie z potrzebami skryptu. Dzieje się tak dzięki funkcji argparse.ArgumentParser.error . Poniższy przykład pokazuje skrypt --foo użycie i komunikat błędu do stderr gdy --foo ale nie --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

Zakładając, że nazwa twojego skryptu to sample.py i uruchamiamy: python sample.py --foo ds_in_fridge

Skrypt będzie narzekał na:

usage: sample.py [-h] [-f FOO] [-b BAR]
sample.py: error: --foo requires --bar. You did not specify bar.

Koncepcyjne grupowanie argumentów za pomocą argparse.add_argument_group ()

Kiedy tworzysz argparse ArgumentParser () i uruchamiasz swój program za pomocą „-h”, pojawia się komunikat o automatycznym użyciu wyjaśniający, z jakimi argumentami możesz uruchomić swoje oprogramowanie. Domyślnie argumenty pozycyjne i argumenty warunkowe są podzielone na dwie kategorie, na przykład tutaj jest mały skrypt (example.py) i dane wyjściowe po uruchomieniu 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

Istnieją sytuacje, w których chcesz podzielić argumenty na dalsze sekcje pojęciowe, aby pomóc użytkownikowi. Na przykład możesz chcieć mieć wszystkie opcje wprowadzania w jednej grupie, a wszystkie opcje formowania wyników w innej. Powyższy przykład można dostosować, aby oddzielić --foo_* od argumentów --bar_* .

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

Który tworzy to wyjście, gdy uruchamiany jest python example.py -h :

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

Zaawansowany przykład z docopt i docopt_dispatch

Podobnie jak w przypadku docopt, w [docopt_dispatch] tworzysz swoje --help w zmiennej __doc__ modułu punktu wejścia. Tam wywołujesz dispatch z ciągiem doc jako argumentem, aby mógł on nad nim analizować parser.

Po wykonaniu tej czynności zamiast ręcznej obsługi argumentów (która zwykle kończy się na wysokiej cyklicznej strukturze if / else), pozostawiasz to do wysyłki, podając tylko sposób obsługi zestawu argumentów.

Do tego służy dekorator dispatch.on : podajesz mu argument lub sekwencję argumentów, które powinny wywołać funkcję, a funkcja ta zostanie wykonana z pasującymi wartościami jako parametrami.

"""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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow