Comment ajouter plusieurs arguments argparse

PythonBeginner
Pratiquer maintenant

Introduction

Ce tutoriel explore comment ajouter et gérer plusieurs arguments de ligne de commande en Python en utilisant le module argparse. Les arguments de ligne de commande permettent aux utilisateurs de personnaliser l'exécution des programmes sans modifier le code lui-même. Le module argparse simplifie ce processus en fournissant des outils pour définir, valider et analyser ces arguments.

À la fin de ce tutoriel, vous comprendrez comment créer des scripts Python capables d'accepter divers paramètres d'entrée, rendant vos applications plus flexibles et conviviales.

Comprendre les bases d'Argparse

La première étape pour travailler avec les arguments de ligne de commande est de comprendre les bases du module argparse.

Qu'est-ce qu'Argparse ?

Argparse est un module Python intégré qui facilite l'écriture d'interfaces de ligne de commande conviviales. Il génère automatiquement des messages d'aide, gère les erreurs et convertit les arguments de ligne de commande en types de données appropriés pour votre programme.

Créer votre premier script avec Argparse

Commençons par créer un script Python simple qui utilise argparse. Nous allons créer un fichier nommé hello.py qui accepte un nom comme argument de ligne de commande.

  1. Ouvrez l'éditeur VSCode et créez un nouveau fichier en cliquant sur "File" > "New File"
  2. Enregistrez le fichier sous le nom hello.py dans le répertoire /home/labex/project
  3. Ajoutez le code suivant au fichier :
import argparse

## Create the parser
parser = argparse.ArgumentParser(description='A simple greeting program')

## Add an argument
parser.add_argument('--name', type=str, default='World', help='Name to greet')

## Parse the arguments
args = parser.parse_args()

## Use the argument
print(f"Hello, {args.name}!")

Ce script démontre les trois étapes principales pour utiliser argparse :

  1. Création d'un objet ArgumentParser
  2. Ajout d'arguments au parser
  3. Analyse des arguments de ligne de commande

Exécution de votre script

Exécutons le script pour voir comment il fonctionne :

  1. Ouvrez un terminal dans l'interface VSCode (Terminal > New Terminal)
  2. Exécutez le script avec la commande suivante :
python3 hello.py

Vous devriez voir cette sortie :

Hello, World!

Maintenant, essayons de passer un nom :

python3 hello.py --name Alice

Sortie :

Hello, Alice!

Comprendre les messages d'aide

L'un des avantages d'argparse est qu'il génère automatiquement des messages d'aide. Essayez d'exécuter :

python3 hello.py --help

Vous devriez voir une sortie similaire à :

usage: hello.py [-h] [--name NAME]

A simple greeting program

options:
  -h, --help   show this help message and exit
  --name NAME  Name to greet

Ce message d'aide est automatiquement généré en fonction de la description que nous avons fournie lors de la création du parser et du texte d'aide que nous avons ajouté à notre argument.

Composants clés d'Argparse

Examinons les principaux composants de notre script :

  • parser = argparse.ArgumentParser(description='...'): Crée un parser avec une description
  • parser.add_argument('--name', ...): Ajoute un argument avec le nom '--name'
  • type=str: Spécifie que l'argument doit être une chaîne de caractères (string)
  • default='World': Définit une valeur par défaut si l'argument n'est pas fourni
  • help='Name to greet': Fournit un texte d'aide pour l'argument
  • args = parser.parse_args(): Analyse les arguments de ligne de commande
  • args.name: Accède à la valeur de l'argument 'name'

Vous comprenez maintenant les bases de l'utilisation d'argparse pour gérer les arguments de ligne de commande en Python.

Ajout de plusieurs types d'arguments

Maintenant que vous comprenez les bases, explorons différents types d'arguments qui peuvent être ajoutés à votre interface de ligne de commande.

Types d'arguments

Argparse prend en charge plusieurs types d'arguments :

  1. Arguments positionnels (Positional arguments) : Arguments obligatoires identifiés par leur position
  2. Arguments optionnels (Optional arguments) : Arguments précédés de -- (ou -) qui peuvent avoir des valeurs par défaut
  3. Arguments drapeau (Flag arguments) : Arguments booléens qui sont soit présents, soit absents
  4. Arguments avec choix (Arguments with choices) : Arguments limités à des valeurs spécifiques

Créons un nouveau script qui démontre ces différents types d'arguments.

  1. Créez un nouveau fichier nommé calculator.py dans le répertoire /home/labex/project
  2. Ajoutez le code suivant :
import argparse

## Create the parser
parser = argparse.ArgumentParser(description='A simple calculator')

## Add a positional argument
parser.add_argument('operation',
                    choices=['add', 'subtract', 'multiply', 'divide'],
                    help='Math operation to perform')

## Add optional arguments
parser.add_argument('--num1', type=float, required=True,
                    help='First number')
parser.add_argument('--num2', type=float, required=True,
                    help='Second number')

## Add a flag argument
parser.add_argument('--verbose', action='store_true',
                    help='Enable verbose output')

## Parse the arguments
args = parser.parse_args()

## Perform the calculation based on the operation
result = 0
if args.operation == 'add':
    result = args.num1 + args.num2
elif args.operation == 'subtract':
    result = args.num1 - args.num2
elif args.operation == 'multiply':
    result = args.num1 * args.num2
elif args.operation == 'divide':
    if args.num2 == 0:
        print("Error: Cannot divide by zero")
        exit(1)
    result = args.num1 / args.num2

## Display the result
if args.verbose:
    print(f"The result of {args.num1} {args.operation} {args.num2} is: {result}")
else:
    print(f"Result: {result}")

Comprendre les nouveaux arguments

Examinons les nouveaux types d'arguments dans ce script :

  1. Argument positionnel (Positional argument) : operation - doit être l'un des éléments suivants : 'add', 'subtract', 'multiply' ou 'divide'

    parser.add_argument('operation',
                        choices=['add', 'subtract', 'multiply', 'divide'],
                        help='Math operation to perform')
  2. Arguments optionnels avec required=True : --num1 et --num2 - doivent être fournis par l'utilisateur

    parser.add_argument('--num1', type=float, required=True,
                        help='First number')
  3. Argument drapeau (Flag argument) : --verbose - lorsqu'il est présent, active la sortie verbeuse

    parser.add_argument('--verbose', action='store_true',
                        help='Enable verbose output')

Tester la calculatrice

Exécutez la calculatrice avec différents arguments pour voir comment elle fonctionne :

python3 calculator.py add --num1 5 --num2 3

Sortie :

Result: 8.0

Essayez avec le drapeau verbose :

python3 calculator.py multiply --num1 4 --num2 7 --verbose

Sortie :

The result of 4.0 multiply 7.0 is: 28.0

Essayez l'opération de division :

python3 calculator.py divide --num1 10 --num2 2

Sortie :

Result: 5.0

Si vous oubliez un argument obligatoire, argparse affichera une erreur :

python3 calculator.py add --num1 5

Sortie :

usage: calculator.py [-h] [--num1 NUM1] [--num2 NUM2] [--verbose]
                    {add,subtract,multiply,divide}
calculator.py: error: the following arguments are required: --num2

Points clés concernant les types d'arguments

  • Les arguments positionnels (Positional arguments) n'ont pas besoin de préfixe et sont identifiés par leur position
  • Le paramètre choices restreint les valeurs valides pour un argument
  • Le paramètre required=True rend un argument optionnel obligatoire
  • Le paramètre action='store_true' crée un drapeau qui est False par défaut et True lorsqu'il est spécifié
  • Le paramètre type convertit l'entrée vers le type spécifié (float dans notre exemple)

Vous savez maintenant comment utiliser différents types d'arguments avec argparse.

Configurations d'arguments avancées

Explorons maintenant des configurations plus avancées pour les arguments, notamment :

  1. Arguments qui acceptent plusieurs valeurs
  2. Arguments avec validation personnalisée
  3. Arguments avec valeurs par défaut
  4. Arguments avec des noms courts (alias d'une seule lettre)

Création d'un script de traitement de fichiers

Créons un script qui démontre ces configurations avancées en construisant un utilitaire de traitement de fichiers.

  1. Créez un nouveau fichier nommé file_processor.py dans le répertoire /home/labex/project
  2. Ajoutez le code suivant :
import argparse
import os

def validate_file(filename):
    """Validate that the file exists."""
    if not os.path.exists(filename):
        raise argparse.ArgumentTypeError(f"File {filename} does not exist")
    return filename

## Create the parser
parser = argparse.ArgumentParser(description='Process text files')

## Multiple values
parser.add_argument('-f', '--files',
                    type=validate_file,
                    nargs='+',
                    help='Input files to process')

## Argument with short name
parser.add_argument('-o', '--output',
                    default='output.txt',
                    help='Output file (default: output.txt)')

## Choices with default
parser.add_argument('-m', '--mode',
                    choices=['read', 'count', 'stats'],
                    default='read',
                    help='Processing mode (default: read)')

## Custom validation for a positive integer
def positive_int(value):
    ivalue = int(value)
    if ivalue <= 0:
        raise argparse.ArgumentTypeError(f"{value} is not a positive integer")
    return ivalue

parser.add_argument('-l', '--lines',
                    type=positive_int,
                    default=10,
                    help='Number of lines to process (default: 10)')

## Parse arguments
args = parser.parse_args()

## Process files based on mode
for file in args.files if args.files else []:
    print(f"Processing file: {file}")

    with open(file, 'r') as f:
        content = f.readlines()

        if args.mode == 'read':
            ## Read mode: output first N lines
            print(f"First {args.lines} lines:")
            for i, line in enumerate(content[:args.lines]):
                print(f"{i+1}: {line.strip()}")

        elif args.mode == 'count':
            ## Count mode: count lines, words, chars
            line_count = len(content)
            word_count = sum(len(line.split()) for line in content)
            char_count = sum(len(line) for line in content)

            print(f"Lines: {line_count}")
            print(f"Words: {word_count}")
            print(f"Characters: {char_count}")

        elif args.mode == 'stats':
            ## Stats mode: line length statistics
            if content:
                line_lengths = [len(line.strip()) for line in content]
                avg_length = sum(line_lengths) / len(line_lengths)
                max_length = max(line_lengths)
                min_length = min(line_lengths)

                print(f"Average line length: {avg_length:.2f}")
                print(f"Shortest line: {min_length} characters")
                print(f"Longest line: {max_length} characters")
            else:
                print("File is empty")

    print("-" * 30)

print(f"Results will be saved to: {args.output}")
## Note: In a real application, we would actually write to the output file

Comprendre les configurations avancées

Examinons les configurations d'arguments avancées :

  1. Plusieurs valeurs avec nargs='+' :

    parser.add_argument('-f', '--files',
                        type=validate_file,
                        nargs='+',
                        help='Input files to process')

    Le paramètre nargs='+' permet à l'utilisateur de fournir un ou plusieurs arguments de fichier.

  2. Fonction de validation personnalisée :

    def validate_file(filename):
        if not os.path.exists(filename):
            raise argparse.ArgumentTypeError(f"File {filename} does not exist")
        return filename

    Cette fonction vérifie si le fichier spécifié existe avant de continuer.

  3. Alias courts avec -o :

    parser.add_argument('-o', '--output',
                        default='output.txt',
                        help='Output file (default: output.txt)')

    Le -o fournit un moyen plus court de spécifier l'argument --output.

  4. Choix avec valeur par défaut :

    parser.add_argument('-m', '--mode',
                        choices=['read', 'count', 'stats'],
                        default='read',
                        help='Processing mode (default: read)')

    Cela limite le mode à des valeurs spécifiques tout en fournissant une valeur par défaut.

Création d'exemples de fichiers de test

Créons deux exemples de fichiers pour tester notre script :

  1. Créez un exemple de fichier nommé sample1.txt :

    echo -e "This is the first line.\nThis is the second line.\nThis is the third line.\nThis is the fourth line.\nThis is the fifth line." > /home/labex/project/sample1.txt
  2. Créez un autre exemple de fichier nommé sample2.txt :

    echo -e "Lorem ipsum dolor sit amet.\nConsectetur adipiscing elit.\nSed do eiusmod tempor incididunt.\nUt labore et dolore magna aliqua." > /home/labex/project/sample2.txt

Tester le processeur de fichiers

Exécutons maintenant le script avec différents arguments :

  1. Utilisation de base avec un fichier :

    python3 file_processor.py -f sample1.txt

    Sortie :

    Processing file: sample1.txt
    First 10 lines:
    1: This is the first line.
    2: This is the second line.
    3: This is the third line.
    4: This is the fourth line.
    5: This is the fifth line.
    ------------------------------
    Results will be saved to: output.txt
  2. Traiter plusieurs fichiers :

    python3 file_processor.py -f sample1.txt sample2.txt

    Sortie :

    Processing file: sample1.txt
    First 10 lines:
    1: This is the first line.
    2: This is the second line.
    3: This is the third line.
    4: This is the fourth line.
    5: This is the fifth line.
    ------------------------------
    Processing file: sample2.txt
    First 10 lines:
    1: Lorem ipsum dolor sit amet.
    2: Consectetur adipiscing elit.
    3: Sed do eiusmod tempor incididunt.
    4: Ut labore et dolore magna aliqua.
    ------------------------------
    Results will be saved to: output.txt
  3. Utiliser le mode count :

    python3 file_processor.py -f sample1.txt -m count

    Sortie :

    Processing file: sample1.txt
    Lines: 5
    Words: 25
    Characters: 135
    ------------------------------
    Results will be saved to: output.txt
  4. Utiliser le mode stats :

    python3 file_processor.py -f sample2.txt -m stats

    Sortie :

    Processing file: sample2.txt
    Average line length: 29.25
    Shortest line: 22 characters
    Longest line: 37 characters
    ------------------------------
    Results will be saved to: output.txt
  5. Limiter le nombre de lignes :

    python3 file_processor.py -f sample1.txt -l 2

    Sortie :

    Processing file: sample1.txt
    First 2 lines:
    1: This is the first line.
    2: This is the second line.
    ------------------------------
    Results will be saved to: output.txt

Points clés concernant les configurations avancées

  • nargs='+' permet plusieurs valeurs d'argument
  • Les fonctions de validation personnalisées aident à garantir une entrée valide
  • Les noms d'arguments courts (alias d'une seule lettre) offrent une commodité
  • Les valeurs par défaut simplifient l'utilisation pour les scénarios courants
  • Le paramètre choices restreint l'entrée aux options valides

Vous avez maintenant appris à configurer des options d'arguments avancées dans vos scripts de ligne de commande.

Construction d'un outil de ligne de commande complet

Dans cette étape, nous allons combiner tout ce que nous avons appris pour construire un outil de ligne de commande complet. Créons un simple gestionnaire de tâches qui permet aux utilisateurs d'ajouter, de lister et de supprimer des tâches à l'aide d'arguments de ligne de commande.

Création du gestionnaire de tâches

  1. Créez un nouveau fichier nommé task_manager.py dans le répertoire /home/labex/project
  2. Ajoutez le code suivant :
import argparse
import json
import os

## File to store tasks
TASKS_FILE = "/home/labex/project/tasks.json"

def load_tasks():
    """Load tasks from the JSON file."""
    if os.path.exists(TASKS_FILE):
        with open(TASKS_FILE, 'r') as f:
            try:
                return json.load(f)
            except json.JSONDecodeError:
                return []
    return []

def save_tasks(tasks):
    """Save tasks to the JSON file."""
    with open(TASKS_FILE, 'w') as f:
        json.dump(tasks, f, indent=2)

def main():
    ## Create the main parser
    parser = argparse.ArgumentParser(description='Task Manager CLI')
    subparsers = parser.add_subparsers(dest='command', help='Command to run')

    ## Add command
    add_parser = subparsers.add_parser('add', help='Add a new task')
    add_parser.add_argument('title', help='Task title')
    add_parser.add_argument('-p', '--priority',
                          choices=['low', 'medium', 'high'],
                          default='medium',
                          help='Task priority (default: medium)')
    add_parser.add_argument('-d', '--due',
                          help='Due date (format: YYYY-MM-DD)')

    ## List command
    list_parser = subparsers.add_parser('list', help='List all tasks')
    list_parser.add_argument('-p', '--priority',
                           choices=['low', 'medium', 'high'],
                           help='Filter tasks by priority')
    list_parser.add_argument('-s', '--sort',
                           choices=['priority', 'title'],
                           default='priority',
                           help='Sort tasks by criteria (default: priority)')

    ## Delete command
    delete_parser = subparsers.add_parser('delete', help='Delete a task')
    delete_parser.add_argument('task_id', type=int, help='Task ID to delete')

    ## Parse arguments
    args = parser.parse_args()

    ## Load existing tasks
    tasks = load_tasks()

    ## Handle commands
    if args.command == 'add':
        ## Add a new task
        new_task = {
            'id': len(tasks) + 1,
            'title': args.title,
            'priority': args.priority,
            'due': args.due
        }
        tasks.append(new_task)
        save_tasks(tasks)
        print(f"Task added: {new_task['title']} (ID: {new_task['id']})")

    elif args.command == 'list':
        ## List tasks
        if not tasks:
            print("No tasks found.")
            return

        ## Filter by priority if specified
        if args.priority:
            filtered_tasks = [t for t in tasks if t['priority'] == args.priority]
        else:
            filtered_tasks = tasks

        ## Sort tasks
        if args.sort == 'priority':
            ## Custom priority sorting
            priority_order = {'high': 0, 'medium': 1, 'low': 2}
            sorted_tasks = sorted(filtered_tasks, key=lambda x: priority_order[x['priority']])
        else:
            ## Sort by title
            sorted_tasks = sorted(filtered_tasks, key=lambda x: x['title'])

        ## Display tasks
        print("ID | Title                 | Priority | Due Date")
        print("-" * 50)
        for task in sorted_tasks:
            due_date = task['due'] if task['due'] else 'N/A'
            print(f"{task['id']:2} | {task['title'][:20]:<20} | {task['priority']:<8} | {due_date}")

    elif args.command == 'delete':
        ## Delete a task
        task_id = args.task_id
        task_found = False

        for i, task in enumerate(tasks):
            if task['id'] == task_id:
                del tasks[i]
                task_found = True
                break

        if task_found:
            save_tasks(tasks)
            print(f"Task {task_id} deleted.")
        else:
            print(f"Task {task_id} not found.")

    else:
        ## No command specified
        parser.print_help()

if __name__ == "__main__":
    main()

Comprendre le gestionnaire de tâches

Ce script démontre plusieurs fonctionnalités avancées d'argparse :

  1. Subparsers (Sous-analyseurs) - Création d'ensembles d'arguments spécifiques à une commande
  2. Arguments spécifiques à une commande - Différents arguments pour les commandes add, list et delete
  3. Validation imbriquée - Choix de priorité limités à des valeurs spécifiques
  4. Valeurs par défaut - Fournir des valeurs par défaut raisonnables pour les arguments optionnels

Tester le gestionnaire de tâches

Exécutons le script avec différentes commandes pour voir comment il fonctionne :

  1. Ajout de tâches :

    python3 task_manager.py add "Complete Python tutorial" -p high -d 2023-12-31

    Sortie :

    Task added: Complete Python tutorial (ID: 1)

    Ajoutez quelques tâches supplémentaires :

    python3 task_manager.py add "Read documentation" -p medium
    python3 task_manager.py add "Take a break" -p low -d 2023-12-25
  2. Liste des tâches :

    python3 task_manager.py list

    Sortie :

    ID | Title                 | Priority | Due Date
    --------------------------------------------------
    1  | Complete Python tutor | high     | 2023-12-31
    2  | Read documentation    | medium   | N/A
    3  | Take a break          | low      | 2023-12-25
  3. Liste des tâches avec filtrage et tri :

    python3 task_manager.py list -s title

    Sortie :

    ID | Title                 | Priority | Due Date
    --------------------------------------------------
    1  | Complete Python tutor | high     | 2023-12-31
    2  | Read documentation    | medium   | N/A
    3  | Take a break          | low      | 2023-12-25
  4. Filtrage par priorité :

    python3 task_manager.py list -p high

    Sortie :

    ID | Title                 | Priority | Due Date
    --------------------------------------------------
    1  | Complete Python tutor | high     | 2023-12-31
  5. Suppression d'une tâche :

    python3 task_manager.py delete 2

    Sortie :

    Task 2 deleted.

    Vérifiez que la tâche a été supprimée :

    python3 task_manager.py list

    Sortie :

    ID | Title                 | Priority | Due Date
    --------------------------------------------------
    1  | Complete Python tutor | high     | 2023-12-31
    3  | Take a break          | low      | 2023-12-25

Obtenir de l'aide pour les sous-commandes

Argparse génère automatiquement de l'aide pour chaque sous-commande :

python3 task_manager.py add --help

Sortie :

usage: task_manager.py add [-h] [-p {low,medium,high}] [-d DUE] title

positional arguments:
  title                 Task title

options:
  -h, --help            show this help message and exit
  -p {low,medium,high}, --priority {low,medium,high}
                        Task priority (default: medium)
  -d DUE, --due DUE     Due date (format: YYYY-MM-DD)

Points clés concernant les sous-analyseurs

  • Les sous-analyseurs créent des ensembles d'arguments spécifiques à une commande
  • Chaque sous-analyseur peut avoir ses propres arguments
  • Le paramètre dest spécifie où le nom de la commande sera stocké
  • Les messages d'aide sont automatiquement générés pour chaque sous-commande
  • Vous pouvez mélanger des arguments positionnels et optionnels dans les sous-analyseurs

Vous disposez maintenant d'un outil de ligne de commande entièrement fonctionnel qui démontre la puissance et la flexibilité d'argparse pour gérer des scénarios d'arguments complexes.

Résumé

Dans ce tutoriel, vous avez appris à utiliser le module argparse de Python pour gérer efficacement les arguments de ligne de commande. Vous avez exploré :

  • Les fonctionnalités de base d'argparse et la création de scripts simples
  • Différents types d'arguments : positionnels, optionnels, indicateurs (flags) et choix
  • Des configurations d'arguments avancées comme les valeurs multiples et la validation personnalisée
  • La construction d'un outil de ligne de commande complet avec des sous-commandes

Ces compétences vous permettent de créer des applications Python plus flexibles et conviviales qui peuvent être configurées via des arguments de ligne de commande sans modifier le code.

L'analyse des arguments de ligne de commande est une compétence essentielle pour les développeurs Python qui souhaitent créer des outils et des utilitaires de qualité professionnelle. Le module argparse fournit un moyen robuste et standardisé de mettre en œuvre cette fonctionnalité dans vos scripts.

Vous pouvez maintenant appliquer ces techniques à vos propres projets Python pour les rendre plus polyvalents et accessibles aux utilisateurs.