Come analizzare gli argomenti della riga di comando in Python

Vuoi eseguire script Python con argomenti della riga di comando? Scopri come analizzare gli argomenti della riga di comando utilizzando i moduli sys, getopt e argparse in Python.

In Python, quando vuoi leggere l’input dell’utente, userai la funzione input(). Tuttavia, per alcune applicazioni, potresti voler passare determinati argomenti durante l’esecuzione dello script dalla riga di comando.

In questo tutorial impareremo come eseguire uno script Python con opzioni e argomenti sulla riga di comando. Impareremo quindi come utilizzare i moduli integrati di Python per analizzare tali opzioni e argomenti.

Cominciamo!

Comprendere sys.argv in Python

Se hai programmato in C, sai che uno dei modi più semplici per passare argomenti al programma è tramite la riga di comando. Per fare ciò, puoi strutturare la funzione principale in questo modo:

#include<stdio.h>

int main(int argc, char **argv){
    //argc: argument count
    //argv: argument vector
    
    //do something on the args

    return 0;
}

Qui, argc sta per numero di argomenti e argv sta per vettore di argomenti.

Esecuzione di script Python con argomenti della riga di comando

In Python, puoi eseguire lo script Python dalla riga di comando usando python3 filename.py. Quando lo fai, puoi anche passare un numero arbitrario di argomenti della riga di comando:

$ python3 filename.py arg1 arg2 ... argn

Il modulo sys fornisce supporto predefinito per accedere ed elaborare questi argomenti della riga di comando. sys.argv è l’elenco di tutti gli argomenti della riga di comando che passiamo quando eseguiamo lo script Python.

Ecco un esempio in cui eseguiamo main.py con argomenti della riga di comando:

$ python3 main.py hello world python script

Possiamo scorrere il vettore dell’argomento usando una semplice funzione for loop and enumerate:

# main.py

import sys

for idx, arg in enumerate(sys.argv):
    print(f"arg{idx}: {arg}")
# Output
arg0:main.py
arg1:hello
arg2:world
arg3:python
arg4:script

Vediamo che il primo argomento (all’indice 0) è il nome del file Python. E gli argomenti successivi iniziano all’indice 1.

Questo è un programma funzionante minimo che accetta ed elabora gli argomenti della riga di comando. Tuttavia, vediamo alcuni problemi:

  • Come fanno gli utenti del programma a sapere quali argomenti passare?
  • E cosa rappresentano questi argomenti?

Questo non è molto chiaro. Per risolvere questo problema, puoi utilizzare i moduli getopt o argparse. E lo impareremo nelle prossime sezioni.✅

Analisi degli argomenti della riga di comando utilizzando getopt di Python

Impariamo come analizzare gli argomenti della riga di comando utilizzando il modulo getopt integrato.

Dopo aver importato getopt dal modulo getopt, puoi specificare gli argomenti da analizzare e le opzioni brevi e le opzioni lunghe con cui eseguire lo script. Dobbiamo analizzare tutti gli argomenti a partire dall’indice 1 in sys.argv. Quindi la sezione da analizzare è sys.argv[1:].

Qui, avremo bisogno di una stringa di messaggio e di un nome file. Usiamo m e f come opzioni brevi e messaggio e file come opzioni lunghe.

Ma come possiamo garantire che un’opzione specifica richieda un argomento?

  • Nelle opzioni brevi, puoi fare in modo che un’opzione richieda un argomento aggiungendo due punti (:) dopo il nome breve dell’opzione.
  • Allo stesso modo, nelle opzioni lunghe, puoi aggiungere un segno = dopo l’opzione lunga. Possiamo catturare queste opzioni e i loro rispettivi argomenti.

Aggiungendoli, avremo il seguente codice in main.py:

# main.py

import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=","file="])

print(opts)
print(args)

Qui, la variabile opts contiene le opzioni e gli argomenti come un elenco di tuple. Qualsiasi altro argomento posizionale che passiamo verrà raccolto nella variabile args.

Possiamo passare il messaggio e il nome del file per eseguire lo script e possiamo utilizzare le opzioni brevi o lunghe.

Eseguendo main.py usando le opzioni lunghe, abbiamo:

$ python3 main.py --message hello --file somefile.txt

Abbiamo le opzioni e gli argomenti come tuple nella variabile opts. Poiché non abbiamo passato alcun argomento posizionale, args è una lista vuota.

# Output
[("--message', 'hello'), ('--file', 'somefile.txt')]
[]

Allo stesso modo, possiamo anche utilizzare le opzioni brevi come mostrato:

$ python3 main.py -m hello -f somefile.txt
# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
[]

⚠️ L’opzione -m short in questo esempio non deve essere confusa con il flag della riga di comando -m che viene utilizzato per eseguire un modulo come modulo principale durante l’esecuzione di uno script Python.

Ad esempio, utilizzerai python3 -m unittest main.py per eseguire unittest come modulo principale durante l’esecuzione di main.py.

Abbiamo detto che tutti gli altri argomenti posizionali che passiamo saranno raccolti nella variabile args. Ecco un esempio:

$ python3 main.py -m hello -f somefile.txt another_argument

L’elenco args contiene l’argomento posizionale another_argument.

# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
['another_argument']

Qui, opts è un elenco di tuple. Quindi possiamo scorrerlo, decomprimere la tupla ed estrarre gli argomenti corrispondenti alle opzioni specifiche.

Ma cosa facciamo con il nome del file e il messaggio dopo aver elaborato questi argomenti? Apriremo il file in modalità di scrittura e scriveremo la stringa del messaggio convertita in maiuscolo nel file.

# main.py
import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=","file="])

print(opts)
print(args)

for option, argument in opts:
    if option == "-m':
        message = argument
    if option == '-f':
        file = argument

with open(file,'w') as f:
    f.write(message.upper())

Eseguiamo main.py con le opzioni brevi e gli argomenti della riga di comando.

$ python main.py -m hello -f thisfile.txt
[('-m', 'hello'), ('-f', 'thisfile.txt')]
[]

Dopo aver eseguito main.py, possiamo vedere “thisfile.txt” nella nostra directory di lavoro. Contiene la stringa ‘hello’ convertita in maiuscolo (‘HELLO’).

$ ls
main.py  thisfile.txt
$ cat thisfile.txt
HELLO

Come analizzare gli argomenti della riga di comando con Argparse

Il modulo argparse, anch’esso integrato nella libreria standard di Python, fornisce funzionalità per analizzare gli argomenti della riga di comando e creare anche interfacce della riga di comando.

Per analizzare gli argomenti della riga di comando, importiamo la classe ArgumentParser dal modulo argparse. Qui abbiamo istanziato arg_parser, un oggetto ArgumentParser:

from argparse import ArgumentParser

arg_parser = ArgumentParser()

Successivamente, vorremmo aggiungere due argomenti della riga di comando:

  • messaggio: la stringa del messaggio, e
  • file: il nome del file con cui vorremmo lavorare.

Ora chiamiamo il metodo add_argument() su arg_parser per aggiungere entrambi questi argomenti. Nella chiamata al metodo add_argument(), puoi impostare help su una stringa (una descrizione dell’argomento).

arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

Finora abbiamo istanziato arg_parser e aggiunto gli argomenti della riga di comando. Quando il programma viene eseguito dalla riga di comando, puoi utilizzare il metodo parse_args() su arg_parser per ottenere i valori degli argomenti.

Qui, catturiamo lo spazio dei nomi dell’argomento nella variabile args. Quindi puoi usare args.argument_name per ottenere i valori degli argomenti.

Dopo aver ottenuto i valori degli argomenti, scriviamo la stringa del messaggio con lo scambio di maiuscole e minuscole (utilizzando il metodo della stringa swapcase()) nel file.

args = arg_parser.parse_args()

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Mettendo tutto insieme, ecco il nostro file main.py:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

args = arg_parser.parse_args()
print(args)

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Comprensione dell’utilizzo degli argomenti della riga di comando

Per comprendere l’uso degli argomenti durante l’esecuzione di main.py, puoi utilizzare l’opzione –help long come mostrato:

$ python3 main.py --help
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

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

Non ci sono argomenti facoltativi e sia il messaggio che il file sono argomenti posizionali obbligatori. In alternativa, puoi anche usare l’opzione breve -h:

$ python3 main.py -h
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

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

Come visto, entrambi gli argomenti sono argomenti posizionali per impostazione predefinita. Quindi, se non passi uno o più di questi argomenti, ti imbatterai in errori.

Qui abbiamo passato un argomento posizionale (Ciao) per la stringa del messaggio, ma non abbiamo fornito alcun valore per l’argomento file.

E otteniamo un errore che indica che l’argomento file è obbligatorio.

$ python3 main.py Hello
usage: main.py [-h] message file
main.py: error: the following arguments are required: file

Quando eseguiamo main.py con entrambi gli argomenti posizionali, vediamo che lo spazio dei nomi args contiene i valori degli argomenti.

$ python3 main.py Hello file1.txt
# Output
Namespace(file="file1.txt", message="Hello")

Ora se esaminiamo il contenuto della presente directory di lavoro, vediamo che lo script crea il file ‘file1.txt’:

$ ls
file1.txt  main.py

La stringa del messaggio originale è ‘Ciao’; dopo aver scambiato le maiuscole e minuscole, la stringa del messaggio nel file ‘file1.txt’ è ‘ciao’.

$ cat file1.txt
hELLO

Come rendere facoltativi gli argomenti della riga di comando

Per rendere facoltativi questi argomenti della riga di comando, è possibile prefissare il nome dell’argomento con –.

Modifichiamo main.py per rendere facoltativi sia il messaggio che gli argomenti del file.

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

Poiché gli argomenti della riga di comando sono entrambi opzionali, possiamo impostare valori predefiniti per questi argomenti.

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message="Python3"
    file="myfile.txt"

A questo punto, il file main.py contiene il seguente codice:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

args = arg_parser.parse_args()
print(args)

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message="Python3"
    file="myfile.txt"

with open(file,'w') as f:
     f.write(message.swapcase())

Se controlliamo l’utilizzo, vediamo che sia message che file sono argomenti opzionali. Ciò significa che ora puoi eseguire main.py senza entrambi questi argomenti.

$ python3 main.py --help
usage: main.py [-h] [--message MESSAGE] [--file FILE]

optional arguments:
  -h, --help         show this help message and exit
  --message MESSAGE  message string
  --file FILE        filename
$ python3 main.py

Nello spazio dei nomi dell’argomento, sia il file che il messaggio sono None.

# Output
Namespace(file=None, message=None)

Vediamo che vengono utilizzati il ​​nome file predefinito e il messaggio ‘myfile.txt’ e ‘Python3’. Il file ‘myfile.txt’ si trova ora nella directory di lavoro:

$ ls
file1.txt  main.py  myfile.txt

E contiene la stringa ‘Python3’ con il caso delle lettere scambiate:

$ cat myfile.txt
pYTHON3

Puoi anche utilizzare entrambi gli argomenti –message e –file per rendere il comando più leggibile.

$ python3 main.py --message Coding --file file2.txt
# Output
Namespace(file="file2.txt", message="Coding")

Vediamo il ‘file2.txt’ nella directory di lavoro:

$ ls
file1.txt  file2.txt  main.py  myfile.txt

E contiene la stringa ‘coDING’ come previsto.

$ cat file2.txt
cODING

Conclusione

Ecco un riepilogo di ciò che abbiamo imparato in questo tutorial:

  • Analogamente al linguaggio di programmazione C, in Python è possibile accedere agli argomenti della riga di comando eseguendo un ciclo del vettore di argomenti sys.argv. sys.argv[0] è il nome dello script Python. Quindi siamo interessati ad analizzare gli argomenti sys.argv[1:].
  • Tuttavia, per migliorare la leggibilità e poter aggiungere opzioni, è possibile utilizzare i moduli getopt e argparse.
  • È possibile utilizzare il modulo getopt per analizzare l’elenco degli argomenti della riga di comando a partire dall’indice 1 fino alla fine dell’elenco. Puoi specificare sia opzioni brevi che opzioni lunghe.
  • Quando un’opzione accetta un argomento, puoi specificare i due punti (:) e = rispettivamente dopo l’opzione short e l’opzione long.
  • Con il modulo argparse di Python, puoi istanziare un oggetto ArgumentParser e usare il metodo add_argument() per aggiungere un argomento posizionale richiesto. Utilizzare — prima del nome dell’argomento per renderlo facoltativo.
  • Per recuperare i valori degli argomenti della riga di comando, chiama il metodo parse_args() sull’oggetto ArgumentParser.

Successivamente, scopri come eseguire l’hashing sicuro in Python.