if __name__ == "__main__"

In questa lezione spiegheremo il funzionamento di una delle righe di codice più comuni e spesso incomprese nel mondo di Python: if __name__ == "__main__".

def main():
    pass

def print_tre_volte(parola):
    print(parola)
    print(parola)
    print(parola)

if __name__ == "__main__":
    main()

Abbiamo l'attributo __name__, che qualora corrisponda alla stringa "__main__" innesca la chiamata alla funzione main(). A cosa serve questa clausola di controllo? E perché si trova così spesso?

Diamo anzitutto uno sguardo alla documentazione ufficiale. Come leggiamo, questa riga consente al nostro codice di capire se stia venendo eseguito come script a sé stante, o se è invece stato richiamato come modulo da un qualche programma per usare una o più delle sua varie funzioni e classi. Possiamo immaginarlo visivamente come una sorta di punto d'ingresso o porta d'accesso al nostro programma. I vantaggi di sapere in che modo il nostro codice sta venendo eseguito sono molteplici e li vedremo tra poco, ma prima è bene capire come fa esattamente a fare ciò.


Cosa succede se il file viene eseguito direttamente come script?

Quando Python esegue del codice assegna alcune variabili speciali, tra cui anche la variabile __name__. Python si rende conto se sta eseguendo questo script direttamente, ad esempio tramite VSCode o dalla shell di sistema:

python script_a.py

In questi casi l'istruzione if fa sì che venga assegnata alla variabile __name__ la stringa "__main__".

>>> print(__name__)
__main__

Quindi in questo caso la condizione di controllo risulta True e la funzione ad essere richiamata è main(), la funzione principale del programma che contiene le prime righe che vogliamo eseguire, ad esempio:

def main():
    print("Prime righe da eseguire SOLO se lo script è stato lanciato 'come programma'")
    print("Lanciato automaticamente se a __name__ è assegnato __main__ ")


Cosa succede se il file se viene importato come modulo in un altro file?

Se invece stiamo richiamando lo script come modulo da dentro a un altro programma, alla variabile __name__ verrà assegnato il nome dello script, quindi il nome del modulo:

# script_b

>>> import script_a 

>>> print(script_a.__name__)

# output
script_a

Possiamo ora comodamente richiamare le funzioni del nostro script_a:

# script_b

>>> import script_a
>>> print(script_a.__name__)

# output
script_a

>>> script_a.print_tre_volte("asd")

# output
asd
asd
asd

Ed ecco quindi svelato il mistero del funzionamento! Tra i casi d'uso in cui questo può tornare utile, c'è la possibilità di continuare a sviluppare del codice che vogliamo testare dall'interno, lasciando comunque la possibilità ad altri programmatori di utilizzare il resto delle nostre funzioni.

def main():
    print("Codice da testare.")
    print("Prime righe da eseguire SOLO se lo script è stato lanciato 'come programma'")
    print("Lanciato automaticamente se a __name__ è assegnato __main__ ")

def print_tre_volte(parola):
    print(parola)
    print(parola)
    print(parola)

if __name__ == "__main__":
    main()

# script_a:

Codice da testare.
Prime righe da eseguire SOLO se lo script è stato lanciato 'come programma'
Lanciato automaticamente se a __name__ è assegnato __main__

Quindi, per sintetizzare il tutto in una frase: utilizziamo if __name__ == "__main__" in tutti quei casi in cui vogliamo che il nostro codice possa avere un doppio comportamento e utilizzo, sia come programma che come modulo.

Happy Coding! :D