Python >> Tutoriel Python >  >> Python

Un guide du module Python argparse

Vous voulez écrire du code plus professionnel et plus propre ? Utilisez le Python module argparse. Cet article vous montrera comment créer une interface de ligne de commande en Python avec arganalyse.

En Python, argparse est l'un de ces modules qui peuvent vous aider à écrire du code Python plus professionnel et plus beau. C'est parce que argparse facilite l'écriture d'interfaces de ligne de commande conviviales. À la fin de cet article, vous aurez acquis une solide connaissance du module argparse - vous pouvez même utiliser l'article comme votre Python argparse aide-mémoire.

Es-tu prêt? Allons-y !

Dans ce guide, voyons si nous pouvons charger une image en utilisant OpenCV à partir de la ligne de commande.

OpenCV est une bibliothèque de vision par ordinateur très populaire. Il effectue diverses tâches pour traiter des images, détecter des objets, etc. Ici, nous l'utiliserons pour avoir quelques exemples visuels d'exécution d'un script à partir de la ligne de commande en utilisant le Python argparse module.

Vous pouvez installer OpenCV directement avec pip :

pip install OpenCV-python  

Puisque nous n'avons pas besoin d'installer Python argparse , nous sommes prêts à partir.

N'hésitez pas à choisir une image de votre choix en suivant ce guide. J'ai pris une photo depuis Unsplash que j'ai renommé 001.jpg pour le rendre facile à travailler. Si vous préférez utiliser Python pour télécharger un fichier directement, vous pouvez apprendre comment le faire ici. (Au fait, consultez mon article sur le renommage des fichiers en Python si vous voulez apprendre à le faire facilement.)

L'interface de ligne de commande que nous allons créer

Tout d'abord, commençons par un script pour charger une image ou la retourner autour de l'axe des x dans OpenCV. Nous voulons exécuter cela à partir de la ligne de commande. En un mot, notre script appellera le imread() et imshow() méthodes de OpenCV pour lire et afficher l'image.

Nous ajouterons également la possibilité d'appeler le flip() méthode de OpenCV pour retourner l'image verticalement. Cela se fera avec un if-else déclaration. Si j'utilise le --flip argument, la sortie sera l'image retournée ; sinon, il affichera simplement l'image.

J'ai créé un fichier nommé display_img_opencv.py avec le code suivant :

import cv2
import argparse

# Construct the argument parser and parse the arguments
arg_desc = '''\
        Let's load an image from the command line!
        --------------------------------
            This program loads an image
            with OpenCV and Python argparse!
        '''
parser = argparse.ArgumentParser(formatter_class = argparse.RawDescriptionHelpFormatter,
                                    description= arg_desc)

parser.add_argument("-i", "--image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")
args = vars(parser.parse_args())


if args["flip"]:
    # Flip the image vertically
    print("[INFO] flipping image vertically...")
    flipped = cv2.imread(args["flip"])
    flip_img = cv2.flip(flipped, 0)
   
    # Display the flipped image and press any key to stop
    cv2.imshow("Flipped vertically", flip_img)
   
else:
    # Load the image with "cv2.imread"
    image = cv2.imread(args["image"])
    # Display the original image
    cv2.imshow("Image", image)

cv2.waitKey(0)

Ensuite, nous pouvons lancer le script avec :

python display_img_opencv.py --image 001.jpg

Et voici le résultat :

Ou nous pouvons retourner l'image verticalement avec l'instruction de ligne de commande suivante :

python display_img_opencv.py --flip 001.jpg

En conséquence, notre image initiale a été retournée autour de l'axe des x .

Vous pouvez arrêter le script en appuyant sur n'importe quelle touche. N'hésitez pas à l'essayer avec votre propre image.

Maintenant, expliquons comment construire l'interface de ligne de commande avec Python argparse module.

Construire une interface de ligne de commande avec argparse de Python

Dans cette section, nous allons apprendre le processus étape par étape pour construire une interface de ligne de commande avec le Python argparse module.

Ajout d'une description de script avec argparse

La première étape consiste à créer un ArgumentParser objet pour contenir toutes les informations nécessaires pour analyser la ligne de commande en Python avant de définir l'analyseur avec le parse_args() méthode.

Remarque : Ici, nous devons envelopper le parse_args() méthode avec le vars() méthode pour éviter une erreur. Vous pouvez vous référer à la section namespace dans la documentation de Python pour plus d'explications.

Ensuite, nous ajoutons également une description au ArgumentParser objet pour expliquer brièvement ce que fait le programme.

La façon la plus simple de le faire est :

parser = argparse.ArgumentParser(description = "Load and flip an image with OpenCV")

Remarque : Vous voudrez peut-être avoir une description mieux formatée, en fonction de vos besoins.

Dans ce cas, j'ai défini ma chaîne de description comme une variable appelée arg_desc , puis je l'ai passé en ArgumentParser() .

Affectation de argparse.RawDescriptionHelpFormatter au formatter_class me permet de formater la description comme je le souhaite.

# Construct the argument parser and parse the arguments
arg_desc = '''\
        Let's load an image from the command line!
        --------------------------------
            This program loads an image
            with OpenCV and Python argparse!
        '''
parser = argparse.ArgumentParser(formatter_class = argparse.RawDescriptionHelpFormatter,
                                    description= arg_desc)

Arguments positionnels dans Python argparse

Ensuite, nous devons ajouter un argument positionnel. Dans ce cas, nous avons deux arguments, un pour charger notre image et un autre pour la retourner verticalement :

parser.add_argument("-i", "--image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")

J'aurais aussi pu écrire ces lignes de code comme suit :

parser.add_argument("image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("flip", metavar="IMAGE_FLIP", help = "Path to your input image")

"image" et "flip" sont appelés arguments de position et font référence à l'action d'attribut. Par défaut, c'est le premier paramètre de add_argument() .

Cependant, vous pouvez également fournir des arguments facultatifs avec une série de drapeaux, comme je l'ai fait dans le premier script. Ces arguments optionnels sont marqués avec - et -- comme préfixes et offrent une certaine flexibilité. Ils peuvent remplacer un argument positionnel.

Accéder aux valeurs argparse

Par défaut, ArgumentParser utilise le dest valeur comme "nom" de chaque objet, mais il est possible de fournir un nom alternatif avec metavar . Cependant, notez que cela ne change que le nom affiché dans help messages (à la place du dest valeur).

parser.add_argument("-i", "--image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")

Dans ce cas, j'ai mis metavar comme "IMAGE" pour le premier dest valeur et "IMAGE_FLIP" pour le second.

Ajout d'aide

Ensuite, nous pouvons définir le paramètre d'aide pour fournir des conseils sur la façon d'utiliser notre script. Dans ce cas, je mets "Path to your input image" . Maintenant, lorsque j'exécute les instructions de ligne de commande suivantes :

python display_img_opencv.py --help

J'ai le résultat suivant :

usage: display_img_opencv.py [-h] [-i IMAGE] [-f IMAGE_FLIP]                                                                                                                                                                                            Let's load an image from the command line!                                                                              --------------------------------                                                                                            This program loads an image                                                                                             with OpenCV and Python argparse!                                                                                                                                                                                                                                                                                                                            optional arguments:                                                                                                       -h, --help            show this help message and exit                                                                   -i IMAGE, --image IMAGE                                                                                                                       Path to your input image                                                                          -f IMAGE_FLIP, --flip IMAGE_FLIP                                                                                                              Path to your input image        

Dans la section suivante, nous verrons comment changer la valeur par défaut d'un indicateur booléen.

Commutation des valeurs par défaut dans argparse

Python prend en charge deux types d'arguments :ceux avec valeur et ceux sans. Par exemple, je peux réécrire mon argument positionnel avec une valeur par défaut - dans ce cas, notre fichier image 001.jpg .

parser.add_argument("-i", "--image", metavar="IMAGE", default="001.jpg", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")

Maintenant, si j'exécute le script en tant que …

python display_img_opencv.py 

… il affichera le fichier image 001.jpg .

Il est également possible d'avoir un argument sans valeur. Dans ce cas, l'argument existe ou non.

Prenons un autre exemple. Nous voulons afficher une image et obtenir des informations sur cette image, telles que ses dimensions et le nombre de canaux. Mais nous ne voulons cette information que si --verbose est spécifié. Sinon, le script n'affichera que l'image sans renvoyer aucune information à son sujet.

import argparse
import cv2

# Construct the argument parser and parse the arguments
arg_desc = '''\
        Let's load an image from the command line!
        --------------------------------
            This program loads an image
            with OpenCV and Python argparse!
        '''

parser = argparse.ArgumentParser(formatter_class = argparse.RawDescriptionHelpFormatter,
                                    description= arg_desc)

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action="store_const", const=False, default=True, help = "Path to your input image")
args = vars(parser.parse_args())

# Load the image with "cv2.imread"
image = cv2.imread(args["image"])
# Dimensions, including width, height, and number of channels
(h, w, c) = image.shape[:3]

if args["verbose"]:
   
    # Display the image width, height, and number of channels   
    print("width: {} pixels".format(w))
    print("height: {}  pixels".format(h))
    print("channels: {}".format(c))

    # Display the image
    cv2.imshow("Image", image)
   
else:
   
    # Display the image
    cv2.imshow("Image", image)

cv2.waitKey(0)

Le action="store_const" Le paramètre signifie que la valeur de l'argument est celle définie dans le const paramètre lorsque l'argument est présent. Si l'argument n'est pas présent, alors il prend la valeur spécifiée par le paramètre par défaut.

Dans la ligne ci-dessus, le script affichera à la fois l'image et les informations qui s'y rapportent par défaut :

python load_img.py -i 001.jpg 
width: 640 pixels
height: 427  pixels
channels: 3

Et l'image :

Nous pouvons également décider de ne pas spécifier de valeur par défaut. Dans ce cas, le default le paramètre sera None . Dans cet exemple, notre argument deviendra False :

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action="store_const", const=False, help = "Path to your input image")

L'exécution du script n'affichera que l'image, sans aucune information.

Maintenant, vous pouvez voir que la valeur de const et default sont généralement opposés dans le cas d'arguments booléens.

Pour faciliter la manipulation, Python a des actions de raccourci appelées store_true et store_false . Le store_true est similaire à const=True et default=False , tandis que store_false est le contraire.

Par exemple, je peux obtenir les informations sur l'image par défaut en définissant action=store_false . Ci-dessous le script modifié :

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action="store_false", help = "Path to your input image")

Maintenant, l'exécution du script affichera l'image ainsi que les informations qui s'y rapportent.

Si vous souhaitez booster vos compétences Python, n'oubliez pas de consulter notre piste de programmation Python. Cela vous aidera à atteindre vos objectifs plus rapidement.

Traitement des données incorrectes

Pour une raison quelconque, vous pouvez entrer des arguments non valides comme arguments de ligne de commande. Dans ce cas, une erreur tuera le script. Cependant, il est possible d'exécuter notre script avec seulement des arguments partiellement corrects.

Une façon de faire est d'ajouter un argument avec le nargs="*" paramètre pour accepter n'importe quel nombre d'arguments, puis ajouter un dictionnaire de valeurs acceptées à parse_args() sans tirets.

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action='store_false', help = "Path to your input image")
parser.add_argument("remainder", nargs="*")
args = vars(parser.parse_args(["v", "i", "image", "verbose"]))

De cette façon, même si nous saisissons un dest incorrect valeurs dans le terminal, notre script fonctionnera toujours. Voici un exemple :

python load_img.py world --cruel happy YEAH 

Comme expliqué précédemment, le script ignore les valeurs inconnues et fonctionne toujours.

Remarque : Une fois que vous avez poussé votre projet vers GitHub, n'oubliez pas d'ajouter les instructions de ligne de commande dans votre README.md fichier :

python display_img_opencv.py image 001.jpg 

Si vous n'êtes pas familier avec GitHub, vous pouvez en savoir plus à ce sujet dans notre article Comment commencer à travailler avec GitHub.

Utiliser argparse avec Pathlib et JSON

Parlons maintenant du paramètre de type. Il est défini comme str by default , mais vous pouvez modifier cette valeur si nécessaire.

Dans l'exemple ci-dessous, nous définissons type=int car nous voulons calculer la valeur cubique d'un entier :

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("cube", help="display a cube of a given number",
                    type=int)
args = parser.parse_args()
print(args.cube**3)
python math.py 5                                
125          

Nous pouvons également utiliser d'autres constructeurs de classe comme types de variables. Vous pouvez apprendre à créer des classes Python ici.

Dans l'exemple suivant, nous combinerons Pathlib avec argparse pour changer de répertoire depuis la ligne de commande.

import argparse
from pathlib import Path

parser = argparse.ArgumentParser()
parser.add_argument("--path", type=Path, default=Path(__file__).absolute().parent, help="Path to the target directory")

args = parser.parse_args()
print(args.path, type(args.path))

Un argument de ligne de commande se présente sous la forme d'une chaîne ; le paramètre de type prendra une fonction qui accepte une chaîne et renvoie une valeur. Ici, réglage type=Path convertira la chaîne en Path objet.

Si vous êtes curieux de savoir Pathlib , vous pouvez en savoir plus ici.

Supposons maintenant que vous vouliez définir un dictionnaire comme argument facultatif. Vous pouvez le faire en utilisant json.loads :

import json
import argparse

dict = '{"name": "img.jpg", "person": "Max", "flower": "tulip", "animal": "lion"}'

# Parse a dict
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', type=json.loads)
args = parser.parse_args(['-i', dict])
print(args.input)

Cela renverra ce qui suit :

{'name': 'img.jpg', 'person': 'Max', 'flower': 'tulip', 'animal': 'lion'}

Vous pouvez en savoir plus sur JSON ici. Si vous ne savez rien sur l'utilisation de fichiers JSON en Python, je vous encourage à rejoindre notre cours sur Comment lire et écrire des fichiers JSON en Python.

Vous pouvez également utiliser argparse pour sérialiser n'importe quelle classe de données de/vers JSON ou YAML .

Enfin et surtout, avec Python argparse , vous pouvez ajouter la prise en charge de la sérialisation/désérialisation de vos propres types personnalisés. Vous pouvez en savoir plus sur la création de vos propres classes personnalisées en Python ici et sur la sérialisation/désérialisation en Python ici.

N'hésitez pas à consulter la documentation Python argparse pour plus de détails.

Que pouvez-vous faire d'autre avec le module Python argparse ?

Dans ce guide du Python argparse module, nous avons appris à ajouter une interface de ligne de commande à notre script Python. Je vous encourage fortement à jouer avec le code et à l'ajouter à vos projets. Cela apportera beaucoup de valeur, et cela ne coûte pas cher.

Vous voulez en savoir plus sur la programmation Python ? Consultez mon article sur l'écriture d'un meilleur code Python pour plus de conseils. Nous avons beaucoup d'autres articles sur LearnPython.com qui couvrent également une variété de sujets.