Arguments de ligne de commande en Python

Vue d’ensemble

Python étant un langage de programmation très populaire, prenant en charge la plupart des systèmes d'exploitation et de nombreuses bibliothèques facilitant le traitement des arguments de ligne de commande, il est devenu largement utilisé pour créer des outils de ligne de commande à de nombreuses fins. Ces outils peuvent aller des simples applications CLI à celles qui sont plus complexes, comme celles d'AWS. awscli outil.

Des outils complexes comme celui-ci sont généralement contrôlés par l'utilisateur via arguments de ligne de commande, qui permet à l'utilisateur d'utiliser des commandes spécifiques, de définir des options, etc. Par exemple, ces options pourraient indiquer à l'outil de générer des informations supplémentaires, de lire des données à partir d'une source spécifiée ou d'envoyer la sortie à un certain emplacement.

En général, les arguments sont transmis différemment aux outils CLI, en fonction de votre système d'exploitation :

  • Comme Unix : - suivi d'une lettre, comme -hou -- suivi d'un mot, comme --help
  • Windows: / suivi soit d'une lettre, soit d'un mot, comme /help

Ces différentes approches existent pour des raisons historiques. De nombreux programmes sur les systèmes de type Unix prennent en charge à la fois la notation à tiret simple et double. La notation en tiret simple est principalement utilisée avec les options à une seule lettre, tandis que les tirets doubles présentent une liste d'options plus lisible, ce qui est particulièrement utile pour les options complexes qui doivent être plus explicites.

Notes: Dans cet article, nous nous concentrerons uniquement sur le format de type Unix de - ainsi que --.

Gardez à l'esprit que le nom et la signification d'un argument sont spécifiques à un programme – il n'y a pas de définition générale, autre que quelques conventions courantes comme --help pour plus d’informations sur l’utilisation de l’outil. En tant que développeur d'un script Python, vous déciderez quels arguments fournir à l'appelant et ce qu'il fera. Cela nécessite une évaluation appropriée.

À mesure que votre liste d’arguments disponibles s’allonge, votre code deviendra plus complexe pour tenter de les analyser avec précision. Heureusement, en Python, il existe un certain nombre de bibliothèques disponibles pour vous aider. Nous aborderons quelques-unes des solutions les plus courantes, qui vont du « bricolage » avec sys.argv, à l'approche « fait pour vous » avec argparse.

Gestion des arguments de ligne de commande avec Python

Python 3+ et l'écosystème qui l'entoure prennent en charge un certain nombre de manières différentes de gérer les arguments de ligne de commande. Il y a de nombreuses bibliothèques qui facilitent l'analyse des arguments de ligne de commande.

La méthode intégrée consiste à utiliser le sys module. En termes de noms et d'utilisation, cela se rapporte directement à la bibliothèque C (libc).

La deuxième façon est la getopt module, qui gère les options courtes et longues, y compris l'évaluation des valeurs des paramètres.

La module d'analyse d'arguments, qui est dérivé du optparse (disponible jusqu'à Python 2.7).

La docopt module, qui est disponible sur GitHub, permet également la même fonctionnalité.

Récemment, l' absl la bibliothèque a également pris de l'ampleur, comme moyen de remplacer optparse ainsi que getopt().

Chacune de ces méthodes a ses avantages et ses inconvénients, il vaut donc la peine de les évaluer pour voir laquelle correspond le mieux à vos besoins.

Le module système

Il s'agit d'un module de base fourni avec Python depuis les premiers jours. Elle adopte une approche très similaire à la bibliothèque C en utilisant argc/argv pour accéder aux arguments. Le module système implémente les arguments de ligne de commande dans une structure de liste simple nommée sys.argv.

Chaque élément de liste représente un seul argument. Le premier élément de la liste, sys.argv[0], est le nom du script Python. Le reste des éléments de la liste, sys.argv[1] à sys.argv[n], sont les arguments de ligne de commande 2 à n.

Un espace est utilisé comme délimiteur entre les arguments. Les valeurs d'argument contenant un espace doivent être entourées de guillemets afin d'être correctement analysées par sys.

L'équivalent de argc est juste le nombre d'éléments dans la liste. Pour obtenir cette valeur, utilisez le Python len() opérateur. Nous montrerons cela dans un exemple de code plus tard.

Impression du premier argument CLI

Dans ce premier exemple, notre script déterminera la manière dont il a été appelé. Ces informations sont conservées dans le premier argument de ligne de commande, indexé à 0. Le code ci-dessous montre comment obtenir le nom de votre script Python :

import sys

print("The script has the name %s" % (sys.argv[0])

Enregistrez ce code dans un fichier nommé arguments-program-name.py, puis appelez-le comme indiqué ci-dessous. Le résultat est le suivant et contient le nom du fichier, y compris son chemin complet :

$ python arguments-program-name.py
The script has the name arguments-program-name.py
$ python /home/user/arguments-program-name.py
The script has the name /home/user/arguments-program-name.py

Comme vous pouvez le voir lors du deuxième appel ci-dessus, nous obtenons non seulement le nom du fichier Python, mais également le chemin complet utilisé pour l'appeler.

Compter le nombre d'arguments

Dans ce deuxième exemple, nous comptons simplement le nombre d'arguments de ligne de commande à l'aide de la fonction intégrée len() méthode. sys.argv est la liste que nous devons examiner. Dans le code ci-dessous, nous obtenons le nombre d'arguments puis soustrayons 1 car l'un de ces arguments (c'est-à-dire le premier) est toujours défini comme nom du fichier, ce qui ne nous est pas toujours utile. Ainsi, le nombre réel d’arguments passés par l’utilisateur est len(sys.argv) - 1:

import sys


arguments = len(sys.argv) - 1
print ("The script is called with %i arguments" % (arguments))

Enregistrez et nommez ce fichier arguments-count.py. Quelques exemples d’appel de ce script sont présentés ci-dessous. Cela comprend trois scénarios différents :

  • Un appel sans aucun autre argument de ligne de commande
  • Un appel avec deux arguments
  • Un appel avec deux arguments, où le second est une chaîne entre guillemets contenant un espace
$ python arguments-count.py
The script is called with 0 arguments
$ python arguments-count.py --help me
The script is called with 2 arguments
$ python arguments-count.py --option "long string"
The script is called with 2 arguments
Itérer à travers les arguments

Notre troisième exemple affiche chaque argument envoyé au script Python, à l'exception du nom du programme lui-même. Par conséquent, nous parcourons les arguments de la ligne de commande en commençant par le seconde élément de liste. Rappelez-vous qu'il s'agit de l'index 1 puisque les listes sont basées sur 0 en Python :

import sys


arguments = len(sys.argv) - 1


position = 1
while (arguments >= position):
    print ("Parameter %i: %s" % (position, sys.argv[position]))
    position = position + 1

Ci-dessous, nous appelons notre code, qui a été enregistré dans le fichier arguments-output.py. Comme dans notre exemple précédent, le résultat illustre trois appels différents :

  • Un appel sans aucun argument
  • Un appel avec deux arguments
  • Un appel avec deux arguments, où le deuxième argument est une chaîne entre guillemets contenant un espace
$ python arguments-output.py
$ python arguments-output.py --help me
Parameter 1: --help
Parameter 2: me
$ python arguments-output.py --option "long string"
Parameter 1: --option
Parameter 2: long string

N'oubliez pas que l'intérêt de montrer l'exemple de chaîne cité est que les paramètres sont généralement délimités par un espace, à moins que ils sont entourés de guillemets.

Drapeaux de rappel (absl)

La bibliothèque Flags d'Abseil est destinée à apporter des arguments de ligne de commande en production, avec des arguments de ligne de commande distribués. Lorsqu'un module utilise des indicateurs de ligne de commande et est importé dans un autre module – l'autre module importe également les drapeaux, et peut les traiter en les transmettant au module importé.

Cela rend les arguments de ligne de commande complexes partagés entre les modules plus faciles et moins verbeux.

De plus, la bibliothèque vous permet de définir les valeurs par défaut, les descriptions et le type de données des arguments, de sorte que des vérifications et conversions supplémentaires ne sont pas nécessaires.

from absl import flags
import sys


flags.DEFINE_string('name', 'User', 'The name of the user.')


FLAGS = flags.FLAGS
FLAGS(sys.argv)

print(f"Hello {FLAGS.name}!")

Les types de données pris en charge sont:

  • DEFINE_integer()
  • DEFINE_string()
  • DEFINE_bool()
  • DEFINE_enum()
  • DEFINE_list()
  • DEFINE_float()

Aussi bien que DEFINE_multi_integer(), DEFINE_multi_string() ainsi que DEFINE_multi_enum() pour la saisie multi-arguments. De plus, en cours d'exécution --help, --helpfull, etc. imprimer les drapeaux existants et leurs descriptions, dans différents formats.

Consultez notre guide pratique et pratique pour apprendre Git, avec les meilleures pratiques, les normes acceptées par l'industrie et la feuille de triche incluse. Arrêtez de googler les commandes Git et en fait apprendre il!

La bibliothèque vous permet également de définir des validations – à la fois en termes de plage, comme des valeurs entières ayant un upper_bound or lower_bound c'est acceptable et exécuter des méthodes arbitraires pour vérifier les valeurs :

def validate_name(value):
    return len(value) > 15

flags.register_validator('name',
                         validate_name,
                         message='Name is over 15 characters long.',
                         flag_values=FLAGS)

En les rassemblant dans un exemple concret :

from absl import flags
import sys

flags.DEFINE_string('name', 'User', 'The name of the user.')
flags.DEFINE_integer('tasks', 0, 'The number of tasks a user has.', lower_bound=0)

FLAGS = flags.FLAGS
FLAGS(sys.argv)

print(f"{FLAGS.name} has {FLAGS.tasks} tasks to work on.")
$ python flags.py --name=John --tasks=5
John has 5 tasks to work on.
$ python flags.py --name=John --tasks=-1

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_flag.py", line 180, in _parse
    return self.parser.parse(argument)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/absl/flags/_argument_parser.py", line 168, in parse
    raise ValueError('%s is not %s' % (val, self.syntactic_help))
ValueError: -1 is not a non-negative integer
...

Le module argparse

La module d'analyse d'arguments est disponible depuis Python 3.2, et une amélioration de la optparse module qui existe jusqu'à Python 2.7. La documentation Python contient une description de l'API et un didacticiel qui couvre toutes les méthodes en détail.

Le module offre une interface de ligne de commande avec une sortie standardisée, alors que les deux premières solutions vous laissent une grande partie du travail. argparse permet la vérification des arguments fixes et facultatifs, avec une vérification du nom en style court ou long. Comme argument facultatif par défaut, il inclut -h, avec sa version longue --help. Cet argument est accompagné d'un message d'aide par défaut décrivant les arguments acceptés.

Le code ci-dessous montre l'initialisation de l'analyseur et la sortie ci-dessous qui montre l'appel de base, suivi du message d'aide. Contrairement aux appels Python que nous avons utilisés dans les exemples précédents, n'oubliez pas d'utiliser Python 3 avec ces exemples :


import argparse


parser = argparse.ArgumentParser()
parser.parse_args()
$ python3 arguments-argparse-basic.py 
$ python3 arguments-argparse-basic.py -h
usage: arguments-argparse-basic.py [-h]

optional arguments:
  -h, --help  show this help message and exit
$ python3 arguments-argparse-basic.py --verbose
usage: arguments-argparse-basic.py [-h]
arguments-argparse-basic.py: error: unrecognized arguments: --verbose

Dans la prochaine étape, nous ajouterons une description personnalisée au message d'aide destiné à nos utilisateurs. Initialiser l'analyseur de cette manière permet d'ajouter un texte supplémentaire. Le code ci-dessous stocke la description dans le text variable, qui est explicitement donnée au argparse classe comme le description paramètre. En appelant ce code ci-dessous, vous pouvez voir à quoi ressemble le résultat :


import argparse


text = 'This is a test program. It demonstrates how to use the argparse module with a program description.'


parser = argparse.ArgumentParser(description=text)
parser.parse_args()
$ python3 arguments-argparse-description.py --help
usage: arguments-argparse-description.py [-h]

This is a test program. It demonstrates how to use the argparse module with a
program description.

optional arguments:
  -h, --help  show this help message and exit

Comme dernière étape, nous ajouterons un argument facultatif nommé -V, qui a un argument de style long correspondant nommé --version. Pour ce faire, nous utilisons la méthode add_argument() que nous appelons avec trois paramètres (affichés pour --version, seulement):

  • Le nom du paramètre : --version
  • Le texte d'aide pour le paramètre : help="show program version"
  • Action (sans valeur supplémentaire) : action="store_true"

Le code source correspondant est affiché ci-dessous. Lire les arguments dans la variable appelée args se fait via le parse_args() méthode de la parser objet. Notez que vous soumettez la version courte et la version longue en un seul appel. Enfin, vous vérifiez si les attributs args.V or args.version sont définis et affichent le message de version :


import argparse


parser = argparse.ArgumentParser()
parser.add_argument("-V", "--version", help="show program version", action="store_true")


args = parser.parse_args()


if args.version:
    print("This is myprogram version 0.1")
$ python3 arguments-argparse-optional.py -V
This is myprogram version 0.1
$ python3 arguments-argparse-optional.py --version
This is myprogram version 0.1

La --version L’argument ne nécessite pas qu’une valeur soit donnée sur la ligne de commande. C'est pourquoi nous définissons l'argument d'action sur "store_true". Dans d'autres cas, vous pourriez avoir besoin d'une valeur attribuée supplémentaire, par exemple si vous spécifiez un certain volume, hauteur ou largeur. Ceci est illustré dans l’exemple suivant. Par défaut, veuillez noter que tous les arguments sont interprétés comme des chaînes :


import argparse


parser = argparse.ArgumentParser()


parser.add_argument("--width", "-w", help="set output width")


args = parser.parse_args()


if args.width:
    print("Set output width to %s" % args.width)

Nous montrons ici ce qui se passe lors de la soumission de différentes valeurs d'argument. Cela inclut à la fois la version courte et la version longue, ainsi que le message d'aide :

$ python3 arguments-argparse-optional2.py -w 10
Set output width to 10
$ python3 arguments-argparse-optional2.py --width 10
Set output width to 10
$ python3 arguments-argparse-optional2.py -h
usage: arguments-argparse-optional2.py [-h] [--width WIDTH]

optional arguments:
  -h, --help            show this help message and exit
  --width WIDTH, -w WIDTH
                        set output width

Le module getopt

Comme vous l'avez peut-être déjà remarqué, le sys Le module divise la chaîne de ligne de commande en facettes uniques uniquement. Le Python module getopt va un peu plus loin et étend la séparation de la chaîne d'entrée par validation des paramètres. Basé sur getopt Fonction C, elle permet à la fois des options courtes et longues, y compris une attribution de valeur.

En pratique, cela nécessite le sys module pour traiter correctement les données d’entrée. Pour ce faire, tant le sys module et le getopt Le module doit être chargé au préalable. Ensuite, de la liste des paramètres d'entrée, nous supprimons le premier élément de la liste (voir le code ci-dessous) et stockons la liste restante des arguments de ligne de commande dans la variable appelée argument_list:


import getopt, sys


full_cmd_arguments = sys.argv


argument_list = full_cmd_arguments[1:]

print argument_list

Les arguments en argument_list peut maintenant être analysé en utilisant le getopts() méthode. Mais avant de faire cela, nous devons dire getopts() sur les paramètres valides. Ils sont définis ainsi :

short_options = "ho:v"
long_options = ["help", "output=", "verbose"]

Cela signifie que ces arguments sont ceux que nous considérons comme valables, accompagnés de quelques informations supplémentaires :

------------------------------------------
long argument   short argument  with value
------------------------------------------
--help           -h              no
--output         -o              yes
--verbose        -v              no
------------------------------------------

Vous avez peut-être remarqué que le o l'option courte était précédée de deux points, :. Cela raconte getopt que cette option doit se voir attribuer une valeur.

Cela nous permet maintenant de traiter une liste d'arguments. Le getopt() La méthode nécessite la configuration de trois paramètres : la liste des arguments réels de argv, ainsi que les options courtes et longues valides (affichées dans l'extrait de code précédent).

L'appel de méthode lui-même est conservé dans une instruction try-catch pour couvrir les erreurs lors de l'évaluation. Une exception est levée si un argument est découvert qui ne fait pas partie de la liste telle que définie précédemment. Le script Python imprimera le message d'erreur à l'écran et se terminera avec le code d'erreur 2 :

try:
    arguments, values = getopt.getopt(argument_list, short_options, long_options)
except getopt.error as err:
    
    print (str(err))
    sys.exit(2)

Enfin, les arguments avec les valeurs correspondantes sont stockés dans les deux variables nommées arguments ainsi que values. Désormais, vous pouvez facilement évaluer ces variables dans votre code. Nous pouvons utiliser un for-loop pour parcourir la liste des arguments reconnus, une entrée après la suivante.


for current_argument, current_value in arguments:
    if current_argument in ("-v", "--verbose"):
        print ("Enabling verbose mode")
    elif current_argument in ("-h", "--help"):
        print ("Displaying help")
    elif current_argument in ("-o", "--output"):
        print (("Enabling special output mode (%s)") % (current_value))

Ci-dessous, vous pouvez voir le résultat de l’exécution de ce code. Nous allons montrer comment le programme réagit avec des arguments de programme valides et non valides :

$ python arguments-getopt.py -h
Displaying help
$ python arguments-getopt.py --help
Displaying help
$ python arguments-getopt.py --output=green --help -v
Enabling special output mode (green)
Displaying help
Enabling verbose mode
$ python arguments-getopt.py -verbose
option -e not recognized

Le dernier appel à notre programme peut sembler un peu déroutant au début. Pour le comprendre, vous devez savoir que les options abrégées (parfois également appelées drapeaux) peuvent être utilisées avec un seul tiret. Cela permet à votre outil d’accepter plus facilement de nombreuses options. Par exemple, appeler python arguments-getopt.py -vh c'est la même chose que d'appeler python arguments-getopt.py -v -h. Ainsi, lors du dernier appel ci-dessus, le getopt le module pensait que l'utilisateur essayait de passer -e comme option, ce qui n'est pas valide.

Conclusion

Dans cet article, nous avons montré de nombreuses méthodes différentes pour récupérer les arguments de ligne de commande en Python, notamment l'utilisation sys, getoptet une argparse. Ces modules varient en fonctionnalités, certains offrant bien plus que d'autres. sys est entièrement flexible, alors que les deux getoptainsi que argparse nécessitent une certaine structure. En revanche, ils couvrent la plupart des travaux complexes que sys c'est à vous de décider. Après avoir parcouru les exemples fournis, vous devriez être en mesure de déterminer quel module convient le mieux à votre projet.

Dans cet article nous n'avons pas parlé d'autres solutions comme la docopts module, nous venons de le mentionner. Ce module suit une approche totalement différente, et sera expliqué en détail dans l'un des prochains articles.

Bibliographie

Horodatage:

Plus de Stackabuse