Cours de Python / Créer une commande et valider ses arguments avec argparse

Le module standard argparse transforme les arguments d’une commande en valeurs utilisables, contrôle leur forme et produit l’aide. Dans cet exercice, vous construisez une commande qui additionne des montants entiers positifs ou nuls, puis vous vérifiez séparément son résultat et son code de sortie.

Distinguer les montants positionnels et l’option de devise

Un argument positionnel est identifié par sa place dans la commande. Ici, amounts désigne les nombres à additionner ; nargs="+" impose au moins une valeur. L’option nommée --currency choisit une étiquette parmi KRW et USD. Si vous l’omettez, le programme affiche KRW.

Le paramètre type=nonnegative ne signifie pas seulement « utiliser un entier » : il appelle notre fonction de conversion pour chaque montant. Celle-ci transforme le texte avec int, refuse les valeurs négatives et lève ArgumentTypeError pour fournir un message à l’analyseur. La somme n’est calculée qu’après la réussite de cette analyse. Le tutoriel officiel argparse présente cette distinction entre arguments positionnels et options.

Les arguments peuvent rester dans l’historique du shell ou apparaître dans la liste des processus. Une option nommée --password ne rendrait pas son contenu secret ; utilisez un mécanisme d’entrée et de gestion des secrets adapté. Pour un nom de fichier contenant des espaces, les guillemets du shell servent à transmettre un seul argument. Notre commande reçoit des nombres, sans ouvrir de fichier.

Enregistrer et exécuter la commande complète

Créez un dossier d’exercice et enregistrez ce fichier en UTF-8 sous le nom sum_cli.py. Ouvrez le terminal dans ce dossier avec l’environnement virtuel du projet sélectionné. Aucune dépendance supplémentaire n’est nécessaire.

import argparse

def nonnegative(text):
    try:
        value = int(text)
    except ValueError as error:
        raise argparse.ArgumentTypeError("expected an integer") from error
    if value < 0:
        raise argparse.ArgumentTypeError("expected a nonnegative amount")
    return value

def main():
    parser = argparse.ArgumentParser(description="Sum expense amounts")
    parser.add_argument("amounts", type=nonnegative, nargs="+")
    parser.add_argument("--currency", choices=["KRW", "USD"], default="KRW", help="Output unit label; no currency conversion")
    args = parser.parse_args()
    print(f"{sum(args.amounts):,} {args.currency}")

if __name__ == "__main__":
    main()

Exécutez python sum_cli.py 3500 8000 2500. Si votre installation macOS ou Ubuntu utilise le nom python3 et qu’aucun environnement virtuel n’est activé, adaptez le nom de l’interpréteur. Le résultat attendu est :

14,000 KRW

Le séparateur de milliers est une virgule parce que le format :, est écrit ainsi dans la chaîne ; il ne dépend pas automatiquement des habitudes typographiques françaises. Le calcul utilise des entiers : 3500.50 n’est pas accepté. La commande ne fixe pas de plafond métier aux montants ; si un domaine impose une limite, celle-ci doit être ajoutée explicitement à la validation.

Essayez ensuite python sum_cli.py 14000 --currency USD : le résultat est 14,000 USD. Aucun taux de change n’intervient. Les nombres saisis doivent déjà être exprimés dans l’unité choisie, et tous les montants d’une même somme doivent avoir cette unité. Pour revenir à l’exemple initial, retirez l’option et reprenez les trois montants de départ.

Contrôler l’aide, les erreurs et le code de sortie

Lancez ces deux commandes l’une après l’autre :

python sum_cli.py --help
python sum_cli.py 0 500 --currency KRW

La première affiche l’aide sans exiger les montants, puis termine normalement. La seconde affiche 500 KRW : zéro est autorisé. L’aide conserve ici les textes anglais définis dans le programme. Sa mise en page et certains détails peuvent varier selon la version de Python ; vérifiez le sens des indications plutôt qu’une copie exacte de tout le texte.

Arguments après sum_cli.py Résultat attendu
0 0 KRW, sortie 0
-1 Montant négatif refusé, sortie 2
abc ou 3.5 Conversion en entier impossible, sortie 2
Aucun argument Au moins un montant requis, sortie 2
500 --currency EUR Devise absente des choix autorisés, sortie 2
--help Aide, sortie 0

Sur PowerShell, consultez $LASTEXITCODE immédiatement après la commande Python. Sur un shell macOS ou Ubuntu, utilisez echo $?. Chaque nouvelle commande peut modifier l’état à examiner : ne lancez pas toute une série d’essais avant de lire le dernier code. Les erreurs d’utilisation passent par la sortie d’erreur ; une sortie standard vide ne suffit donc pas à conclure qu’il ne s’est rien produit.

Avec les réglages de cet exemple, argparse affiche l’usage et quitte avec le code 2 lorsqu’un argument est invalide. La référence officielle de la conversion des arguments détaille les convertisseurs et les exceptions reconnues. Après chaque erreur volontaire, relancez python sum_cli.py 3500 8000 2500 pour confirmer que la commande valide fonctionne toujours.

Garder le calcul réutilisable lors d’une extension

Un analyseur prépare les données d’entrée ; il ne doit pas devenir l’unique endroit où toutes les règles du programme sont cachées. Pour une évolution de cet exercice, une fonction de calcul peut recevoir une liste de nombres et renvoyer un total, tandis que main conserve l’analyse et l’affichage. Cette séparation prolonge la distinction entre paramètre et valeur de retour abordée dans le cours sur les fonctions.

Lorsque plusieurs opérations sont nécessaires, des sous-commandes telles que init, add et list peuvent être définies avec add_subparsers. Chacune doit avoir une entrée, un effet et une réponse d’échec explicites. Transmettez aux fonctions seulement les valeurs utiles, au lieu de les rendre dépendantes d’un objet Namespace partout dans le programme.

Pour vérifier une évolution, conservez une commande valide de référence puis changez une seule entrée à la fois : zéro, valeur négative, absence de montant ou devise inconnue. Contrôlez le résultat, le message pertinent et le code de sortie. Un test du texte intégral de l’aide serait plus fragile qu’un contrôle des options proposées et de la réussite de --help.