Recherche…


Introduction

La plupart des outils de ligne de commande reposent sur des arguments transmis au programme lors de son exécution. Au lieu de demander une entrée, ces programmes attendent que les données ou les indicateurs spécifiques (qui deviennent des booléens) soient définis. Cela permet à l'utilisateur et aux autres programmes d'exécuter le fichier Python en lui transmettant les données au démarrage. Cette section explique et démontre l'implémentation et l'utilisation des arguments de ligne de commande dans Python.

Bonjour tout le monde en argparse

Le programme suivant dit bonjour à l'utilisateur. Il prend un argument positionnel, le nom de l'utilisateur, et peut également être dit le message d'accueil.

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!

Pour plus de détails, veuillez lire la documentation d'argparse .

Exemple basique avec docopt

docopt tourne l'argument d'analyse de ligne de commande sur sa tête. Au lieu d'analyser les arguments, il vous suffit d' écrire la chaîne d'utilisation de votre programme, et docopt analyse la chaîne d'utilisation et l'utilise pour extraire les arguments de la ligne de commande.

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

Échantillon exécute:

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

Définir des arguments mutuellement exclusifs avec argparse

Si vous souhaitez que deux ou plusieurs arguments soient mutuellement exclusifs. Vous pouvez utiliser la fonction argparse.ArgumentParser.add_mutually_exclusive_group() . Dans l'exemple ci-dessous, foo ou bar peut exister mais pas les deux en même temps.

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

Si vous essayez d'exécuter le script en spécifiant à la fois les arguments --foo et --bar , le script se plaindra du message ci-dessous.

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

Utilisation d'arguments en ligne de commande avec argv

Chaque fois qu'un script Python est appelé à partir de la ligne de commande, l'utilisateur peut fournir des arguments de ligne de commande supplémentaires qui seront transmis au script. Ces arguments seront disponibles pour le programmeur de la variable système sys.argv ( « argv » est un nom traditionnel utilisé dans la plupart des langages de programmation, et cela signifie « arg ument v ecteur »).

Par convention, le premier élément de la liste sys.argv est le nom du script Python lui-même, tandis que le reste des éléments sont les jetons transmis par l'utilisateur lors de l'appel du script.

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

Voici un autre exemple d'utilisation de argv . Nous enlevons d'abord l'élément initial de sys.argv car il contient le nom du script. Ensuite, nous combinons le reste des arguments en une seule phrase et imprimons finalement cette phrase en préfixant le nom de l'utilisateur actuellement connecté (pour qu'il émule un programme de discussion).

import getpass
import sys

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

L'algorithme couramment utilisé lors de l'analyse "manuelle" d'un certain nombre d'arguments non positionnels consiste à parcourir la liste sys.argv . L'une des façons consiste à parcourir la liste et à en afficher chaque élément:

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

Message d'erreur d'analyseur personnalisé avec argparse

Vous pouvez créer des messages d'erreur d'analyseur en fonction des besoins de votre script. Ceci est à travers la fonction argparse.ArgumentParser.error . L'exemple ci-dessous montre le script imprimant une utilisation et un message d'erreur à stderr lorsque --foo est donné mais pas --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

En supposant que votre nom de script est sample.py, et que nous python sample.py --foo ds_in_fridge : python sample.py --foo ds_in_fridge

Le script se plaindra de ce qui suit:

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

Groupement conceptuel d'arguments avec argparse.add_argument_group ()

Lorsque vous créez un argumentse ArgumentParser () et exécutez votre programme avec '-h', vous obtenez un message d'utilisation automatisé expliquant avec quels arguments vous pouvez exécuter votre logiciel. Par défaut, les arguments positionnels et les arguments conditionnels sont séparés en deux catégories. Par exemple, voici un petit script (example.py) et la sortie lorsque vous exécutez 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

Dans certaines situations, vous souhaitez séparer vos arguments en d'autres sections conceptuelles pour aider votre utilisateur. Par exemple, vous pouvez souhaiter avoir toutes les options de saisie dans un groupe et toutes les options de format de sortie dans un autre. L'exemple ci-dessus peut être ajusté pour séparer les --foo_* des --bar_* comme ceci.

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

Qui produit cette sortie lorsque python example.py -h est exécuté:

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

Exemple avancé avec docopt et docopt_dispatch

Comme avec docopt, avec [docopt_dispatch] vous créez votre --help dans la variable __doc__ de votre module de point d'entrée. Là, vous appelez dispatch avec la chaîne de caractères en argument, afin de pouvoir exécuter l'analyseur dessus.

Cela étant, au lieu de manipuler manuellement les arguments (qui se terminent généralement par une structure if / else cyclomatique élevée), vous laissez le soin d’expédier uniquement en fonction de la manière dont vous souhaitez gérer l’ensemble des arguments.

C'est à cela que sert le décorateur dispatch.on : vous lui donnez l'argument ou la séquence d'arguments qui devrait déclencher la fonction, et cette fonction sera exécutée avec les valeurs correspondantes en tant que paramètres.

"""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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow