Menu

if __name__ == '__main__' in Python: la guardia main spiegata

Cosa fa davvero if __name__ == '__main__', perché ogni script Python serio finisce per usare questo schema e come strutturare un file che sia insieme script e modulo.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

La riga più strana di Python, svelata

Apri quasi qualsiasi file Python e prima o poi troverai questo in fondo:

if __name__ == "__main__":
    main()

Sembra un pezzo di codice boilerplate magico. In realtà è una funzionalità molto pratica, una volta capito cosa fa, ed esiste perché Python non traccia una linea netta tra "script" e "librerie".

Il contesto: due modi di usare un file

Ogni file .py in Python può essere usato in due modi diversi:

  1. Come script: lo esegui direttamente con python3 file.py.
  2. Come modulo: un altro file lo importa con import file.

Il linguaggio non ti obbliga a dichiarare quale dei due stai scrivendo. Qualsiasi file potrebbe finire per fare entrambe le cose.

Prendi un file chiamato math_helpers.py:

# math_helpers.py
def mean(values):
    return sum(values) / len(values)

def median(values):
    s = sorted(values)
    mid = len(s) // 2
    if len(s) % 2 == 0:
        return (s[mid - 1] + s[mid]) / 2
    return s[mid]

# Test veloce durante lo sviluppo
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("mean:", mean(numbers))
print("median:", median(numbers))

Se esegui questo file direttamente, stampa l'output del test: ottimo. Ma se un altro file fa import math_helpers, quelle istruzioni print vengono eseguite durante l'import. Chiunque usi il modulo vede i tuoi output di prova. Non proprio ottimo.

Cos'è __name__

Ogni modulo Python ha una variabile integrata chiamata __name__. Python la imposta automaticamente:

  • Quando il file viene importato, __name__ prende il nome con cui il modulo è stato importato: "math_helpers" nell'esempio sopra.
  • Quando il file viene eseguito direttamente, Python imposta __name__ alla stringa speciale "__main__".

Questo ti dà un modo per capire in quale modalità ti trovi. Avvolgi il codice "solo per lo script" in un controllo:

# math_helpers.py
def mean(values):
    return sum(values) / len(values)

def median(values):
    s = sorted(values)
    mid = len(s) // 2
    if len(s) % 2 == 0:
        return (s[mid - 1] + s[mid]) / 2
    return s[mid]

if __name__ == "__main__":
    numbers = [3, 1, 4, 1, 5, 9, 2, 6]
    print("mean:", mean(numbers))
    print("median:", median(numbers))

Ora python3 math_helpers.py stampa l'output del test. Ma import math_helpers da un altro file salta del tutto il blocco: le funzioni sono disponibili e non parte niente di indesiderato.

Il compagno abituale: una funzione main()

La maggior parte degli script reali finisce per avere una funzione main() dedicata e tiene minuscolo il blocco della guardia:

# process_orders.py
import sys

def load_orders(path):
    with open(path) as f:
        return [line.strip() for line in f if line.strip()]

def process(orders):
    for order in orders:
        print(f"Processing {order}")

def main():
    if len(sys.argv) < 2:
        print("Usage: python3 process_orders.py <file>")
        sys.exit(1)
    orders = load_orders(sys.argv[1])
    process(orders)

if __name__ == "__main__":
    main()

Perché scomodarsi con una main() invece di mettere la logica direttamente sotto la guardia if?

  1. Testabilità. Puoi importare il modulo e chiamare main() (o una qualsiasi delle funzioni di supporto) dai test.
  2. Variabili locali. Tutto ciò che definisci dentro main() è una variabile locale, non un nome a livello di modulo. Eviti così collisioni di nomi accidentali e l'interfaccia pubblica del modulo resta più pulita.
  3. Leggibilità. Il blocco della guardia ora è di due righe: un chiaro "punto di ingresso dello script" invece di un mucchio di logica.

Una rapida dimostrazione

Puoi osservare il comportamento direttamente:

Quando esegui il frammento qui sopra con Python, stampa __name__ is: __main__ e "being run as a script." Se un altro file importasse questo, lo stesso controllo stamperebbe l'altro ramo.

Quando la guardia non serve

Molti file Python non ne avranno mai una. Gli script brevi che nessuno importerebbe mai vanno benissimo anche senza:

# one_off_rename.py
import os
for name in os.listdir("."):
    if name.endswith(".txt"):
        os.rename(name, name.lower())

Va benissimo così. Non stai costruendo una libreria; nessuno importerà questo file. Però, nel momento in cui un file contiene logica riutilizzabile e vuoi tenerci accanto del codice con effetti collaterali, usa la guardia.

Punti di ingresso per i pacchetti installati

Quando pubblichi il tuo codice come un vero pacchetto, esiste un meccanismo più formale: gli entry_points nei metadati del pacchetto, che associano un comando a una funzione. Chi installa il tuo pacchetto ottiene un comando da shell che chiama direttamente la funzione. Ma per gli script che esegui da una cartella sul tuo computer, la guardia __main__ è lo strumento standard.

Riepilogo del capitolo

Ora hai:

  • Le funzioni per dare un nome alla tua logica.
  • *args/**kwargs per chiamate flessibili.
  • Le lambda per funzioni usa e getta.
  • I decoratori e i type hint per avvolgere e documentare quelle funzioni.
  • Moduli, pip e ambienti virtuali per suddividere il codice tra file e progetti.
  • La guardia __main__ per far convivere script e moduli.

Prossimo argomento: le classi

Finora hai abbinato soprattutto funzioni a dati semplici: dict, liste, tuple. Il prossimo capitolo introduce le classi, il modo in cui Python lega insieme dati e comportamento, e il luogo in cui vivono concetti come self, __init__, l'ereditarietà e le dataclass.

Domande frequenti

Cosa fa if __name__ == '__main__'?

Esegue il blocco sottostante solo quando il file viene eseguito direttamente (non quando viene importato come modulo). Così puoi scrivere un file .py che si può sia eseguire come script sia importare per le sue funzioni e classi, senza che le azioni dello script partano durante l'import.

In Python serve una funzione main?

No. I file Python vengono eseguiti automaticamente dall'alto verso il basso. Però, non appena un file contiene logica che vuoi rendere anche importabile, la guardia if __name__ == '__main__' diventa importante, e mettere il lavoro principale dello script dentro una funzione main() è un'abitudine che di solito l'accompagna.

Che differenza c'è tra __name__ e __main__?

__name__ è una variabile speciale che Python imposta in ogni modulo. Se il file viene importato, __name__ è il nome del modulo (per esempio 'util'). Se il file viene eseguito direttamente, Python imposta __name__ alla stringa '__main__'. Il controllo if confronta le due cose.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA