Corso Python / Argomenti da riga di comando e argparse

argparse permette di definire gli argomenti di un comando Python, convertirli nel tipo richiesto e limitare i valori ammessi. Genera inoltre aiuto e messaggi di uso errato, così puoi offrire un’interfaccia coerente senza interpretare manualmente ogni elemento di sys.argv.

Distinguere argomenti posizionali e opzioni

Un argomento posizionale viene riconosciuto dalla posizione nel comando; un’opzione come --currency USD ha un nome che ne esplicita il significato. Nel programma seguente amounts raccoglie gli importi e --currency sceglie l’etichetta da stampare.

Impostazione Effetto nell’esempio
nargs="+" Richiede almeno un importo e raccoglie gli importi in una lista.
type=nonnegative Converte ogni testo in intero e rifiuta valori negativi.
choices=["KRW", "USD"] Accetta soltanto queste due etichette, rispettando maiuscole e minuscole.
default="KRW" Usa KRW quando l’opzione non viene fornita.

argparse appartiene alla libreria standard. La documentazione ufficiale di argparse descrive gli argomenti, i convertitori, gli errori e i sottocomandi. I messaggi generati possono differire tra versioni; questo esempio non richiede le opzioni aggiunte dalle versioni più recenti.

Non inserire password o token negli argomenti: possono rimanere nella cronologia della shell o comparire nell’elenco dei processi. Un’opzione con un nome chiaro non protegge il suo valore. Per strumenti che accettano percorsi, racchiudi tra virgolette i percorsi con spazi affinché la shell li passi come un solo argomento.

Eseguire il programma completo di somma

Crea una cartella di esercitazione e salva il file sum_cli.py in UTF-8. Apri il terminale in quella cartella e seleziona l’ambiente Python del progetto. Il contenuto completo è:

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

nonnegative prova a convertire il testo con int. Se la conversione fallisce, solleva ArgumentTypeError mantenendo la causa; se l’intero è negativo, fornisce un errore specifico. In entrambi i casi argparse presenta il problema all’utente senza arrivare alla somma.

Da quella cartella esegui python sum_cli.py 3500 8000 2500. Se il tuo ambiente macOS o Ubuntu espone l’interprete come python3, usa quel nome al posto di python. Il risultato atteso è:

14,000 KRW

La virgola in :, formatta le migliaia; non imposta la valuta né applica una convenzione locale italiana. Il blocco if __name__ == "__main__" avvia main quando esegui il file e permette di importarlo senza leggere immediatamente gli argomenti del processo chiamante.

Controllare aiuto, errori e codici di uscita

Prova separatamente questi due comandi:

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

Il primo stampa l’aiuto anche senza importi e termina con codice 0. Il secondo accetta zero, stampa 500 KRW e termina con codice 0. I testi dell’aiuto rimangono in inglese perché sono quelli del programma e della libreria mostrati nell’esempio.

Prova poi python sum_cli.py -1, python sum_cli.py abc, python sum_cli.py e python sum_cli.py 500 --currency EUR. Il primo viola il limite sul valore; il secondo non è convertibile in intero; il terzo non soddisfa nargs="+"; il quarto viola choices. Questi errori d’uso terminano con codice 2 e presentano la spiegazione sul canale degli errori, invece di produrre una somma valida.

Controlla il codice immediatamente dopo ogni esecuzione con $LASTEXITCODE in PowerShell oppure echo $? in una shell macOS/Ubuntu. Non lanciare prima un altro programma esterno: potresti leggere il suo stato al posto di quello del comando che stai verificando. Dopo le prove torna a un ingresso valido e verifica nuovamente risultato e codice 0.

--currency sceglie soltanto un’etichetta, senza conversione valutaria. Con python sum_cli.py 14000 --currency USD ottieni 14,000 USD: non hai convertito 14.000 won in dollari. Inserisci importi già espressi nella stessa unità scelta. Il programma non gestisce centesimi decimali: un testo come 8.50 non è un intero e viene rifiutato.

Estendere l’interfaccia mantenendo separati i calcoli

Se lo strumento deve svolgere operazioni diverse, add_subparsers può organizzare sottocomandi come init, add e list, ciascuno con i propri argomenti. Il programma qui sopra offre solo la somma: quei sottocomandi richiedono un’estensione esplicita e non sono già disponibili.

Nel passaggio a un programma più ampio, estrai il calcolo in una funzione che riceva i valori necessari e restituisca un risultato. Evita di far dipendere tale funzione da un argparse.Namespace: potrai riutilizzarla in test o altre interfacce. La lezione sulle funzioni e sui valori restituiti spiega questa separazione.

Per ogni nuova opzione verifica un ingresso ordinario, il limite ammesso, l’assenza dell’argomento, un valore non consentito e l’aiuto. Controlla il significato del messaggio e il codice di uscita; non rendere il test dipendente dall’intero testo dell’aiuto, dal percorso dell’eseguibile o dalla sua impaginazione.