if __name__ == "__main__" in Python - guida pratica

25 luglio 2026

Interfaccia di personalizzazione connettori, dove è selezionato wordpress per lo sviluppo locale. Claude può usare strumenti come get_recent_posts.

Indice

Un programma Python può contenere funzioni riutilizzabili e, allo stesso tempo, comportarsi come uno script eseguibile. La condizione if __name__ == "__main__": serve proprio a separare questi due comportamenti, evitando che operazioni come stampe, chiamate API o connessioni al database partano automaticamente durante un import. In questa guida mostro come funziona, quando usarla e come applicarla a uno script con SQLite.

La regola che separa codice riutilizzabile ed esecuzione diretta

  • Esecuzione diretta significa avviare il file con Python e attivare il blocco principale.
  • Durante un import, __name__ contiene il nome del modulo, non __main__.
  • Il blocco protetto evita effetti collaterali indesiderati quando il file viene importato.
  • La funzione main() è una convenzione utile, non una parola riservata di Python.
  • Con SQLite è buona pratica aprire la connessione solo nel flusso principale.

Che cosa controlla davvero __name__

Ogni modulo Python possiede una variabile speciale chiamata __name__. Quando lancio direttamente un file, l’interprete assegna a quella variabile il valore __main__; quando invece importo lo stesso file, usa il nome del modulo.

La condizione confronta quindi due stringhe. Se il confronto è vero, Python esegue il codice indentato sotto l’if; se è falso, quel blocco viene saltato. Il resto del file, comprese le definizioni di funzioni e classi, può comunque essere caricato.

def saluta():
    return "Ciao dal modulo"

if __name__ == "__main__":
    print(saluta())

Avviando il file con python saluto.py, vedo il messaggio nel terminale. Se scrivo invece import saluto da un altro programma, la funzione viene resa disponibile ma il print non parte. È questa distinzione a rendere il file sia eseguibile sia riutilizzabile.

Che differenza c’è tra avvio diretto e importazione

Il comportamento diventa più chiaro osservando i tre casi più comuni. La differenza non riguarda soltanto la visualizzazione di un messaggio: può determinare se vengono eseguite query, creati file o aperte connessioni esterne.

Modalità Valore di __name__ Blocco principale
python script.py __main__ Viene eseguito
import script script Non viene eseguito
python -m pacchetto.script __main__ Viene eseguito

Durante un import, Python esegue comunque le istruzioni presenti al livello superiore del modulo. Per questo considero rischioso inserire direttamente fuori dal blocco protetto operazioni come scritture su database, richieste HTTP o cancellazioni di file.

Il controllo non blocca l’importazione dell’intero file e non crea una sandbox. Protegge soltanto le istruzioni contenute nel blocco condizionale, lasciando disponibili le funzioni e le classi che servono agli altri moduli.

Perché conviene chiamare una funzione main

Per un esempio di due righe si potrebbe inserire direttamente il codice sotto la condizione. Nei progetti reali preferisco però definire una funzione main() e usarla come punto di ingresso, perché il flusso diventa più leggibile e più semplice da testare.

def main():
    nome = input("Come ti chiami? ")
    print(f"Ciao, {nome}!")
    return 0

if __name__ == "__main__":
    raise SystemExit(main())

In questo schema main() restituisce un codice di uscita. Il valore 0 indica normalmente un’esecuzione riuscita, mentre un numero diverso da zero può segnalare un errore a uno script di shell, a una pipeline CI/CD o a un orchestratore cloud.

La funzione non deve chiamarsi per forza main. Il nome è una convenzione molto diffusa, utile perché comunica immediatamente il ruolo della funzione. Il vero elemento che controlla l’avvio è il confronto tra __name__ e __main__.

Un esempio pratico con SQLite

Il caso dei database mostra bene il vantaggio del costrutto. Immagino un modulo che contiene una funzione per creare una tabella e una funzione principale che apre il database, inserisce un record e chiude la connessione.

import sqlite3

def crea_tabella(connessione):
    connessione.execute("""
        CREATE TABLE IF NOT EXISTS utenti (
            id INTEGER PRIMARY KEY,
            nome TEXT NOT NULL
        )
    """)

def inserisci_utente(connessione, nome):
    connessione.execute(
        "INSERT INTO utenti (nome) VALUES (?)",
        (nome,)
    )

def main():
    with sqlite3.connect("archivio.db") as connessione:
        crea_tabella(connessione)
        inserisci_utente(connessione, "Luca")
    print("Utente salvato")

if __name__ == "__main__":
    raise SystemExit(main())

Se eseguo il file direttamente, SQLite crea o aggiorna archivio.db. Se importo il modulo per riutilizzare inserisci_utente() in un’applicazione web, il database non viene modificato automaticamente. Per me questo è il punto più importante: le funzioni descrivono le operazioni, mentre main() decide quando eseguirle.

Nel codice uso i segnaposto ? invece di concatenare stringhe SQL. È una scelta essenziale per evitare SQL injection e per gestire correttamente valori contenenti apostrofi o caratteri speciali. Il guard clause non sostituisce le buone pratiche del database, ma impedisce che una semplice importazione avvii operazioni non richieste.

Gli errori che fanno inciampare più spesso

Confondere una variabile normale con quella speciale

La forma corretta usa due underscore prima e dopo i nomi: __name__ e __main__. Scrivere una variante con un solo underscore crea un controllo diverso e generalmente non produce il comportamento atteso.

Chiamare main prima di definirla

Python esegue le istruzioni dall’alto verso il basso. Se il blocco finale chiama main() prima che la funzione sia stata definita, ottengo un NameError. Tengo quindi definizioni e funzioni sopra il punto di ingresso.

Mettere effetti collaterali fuori dal blocco

Importare una libreria standard, definire una costante o dichiarare una funzione è normalmente innocuo. Aprire una connessione, modificare una tabella o lanciare un processo esterno è diverso: queste operazioni dovrebbero partire dentro main() o dentro una funzione chiamata esplicitamente.

Leggi anche: API informatiche - come funzionano e quale approccio scegliere

Pensare che il blocco protegga ogni importazione

Il contenuto al livello superiore viene comunque valutato durante l’import. Se un modulo importato a sua volta contiene codice operativo fuori dal proprio blocco principale, quel codice può partire. Quando qualcosa si comporta in modo inatteso, controllo quindi tutta la catena degli import, non soltanto il file che sto eseguendo.

Come usarlo bene in test e progetti più grandi

Separare la logica dalle operazioni di avvio rende i test più semplici. Posso importare una funzione, passarle dati fittizi e verificare il risultato senza simulare ogni volta l’avvio da terminale o la configurazione completa dell’applicazione.

Nei progetti più strutturati, mantengo nel modulo principale soltanto un avvio leggero e sposto la logica in funzioni dedicate. Per esempio, una funzione può leggere gli argomenti, una può validare i dati e una può gestire la persistenza. Questa divisione riduce il rischio che un test apra davvero un database di produzione.

Quando lo script cresce, conviene aggiungere strumenti come argparse per gli argomenti da riga di comando e registrare gli errori in modo esplicito. La condizione di ingresso resta utile, ma non deve diventare un contenitore di cinquanta istruzioni difficili da mantenere.

Il punto di ingresso che mantiene il codice sotto controllo

La regola pratica è semplice: definisco funzioni e classi riutilizzabili, raccolgo l’avvio in main() e chiamo quella funzione soltanto quando il file viene eseguito direttamente. In questo modo importazioni, test, script automatici e operazioni sul database restano separati e prevedibili.

Non è una formula magica né un obbligo imposto dal linguaggio. È una convenzione piccola, ma con un effetto concreto sulla qualità del codice: riduce le sorprese, chiarisce il flusso di esecuzione e lascia aperta la strada alla trasformazione di uno script in un modulo vero e proprio.

Domande frequenti

Quando avvii direttamente un file, __name__ vale __main__ e il blocco condizionale viene eseguito. Durante un import, invece, contiene il nome del modulo: funzioni e classi vengono caricate, ma il blocco protetto viene saltato.

main() rende il flusso più leggibile e semplice da testare. Può restituire un codice di uscita, normalmente 0 in caso di successo, da passare alla shell con raise SystemExit(main()).

Definisci funzioni come crea_tabella() e inserisci_utente(), ma apri la connessione dentro main(). In questo modo l’esecuzione diretta può creare o aggiornare archivio.db, mentre l’importazione del modulo non modifica automaticamente il database.

Importazioni, costanti e definizioni di funzioni o classi sono normalmente adatte al livello superiore. Connessioni, query, richieste HTTP, scritture su file e processi esterni dovrebbero partire dentro main() o in una funzione chiamata esplicitamente, considerando anche gli effetti collaterali dei moduli importati.

Valuta l'articolo

Valutazione: 0.00 Numero di voti: 0

Tag:

python sqlite moduli testing argparse

Condividi post

Sandro Grasso

Sandro Grasso

Sono Sandro e da 3 anni seguo con curiosità il mondo dell'informatica, dell'intelligenza artificiale e delle soluzioni cloud. Ho iniziato questo percorso perché sono affascinato da come queste tecnologie stiano plasmando il nostro futuro e desidero aiutare chi legge a navigare in questo mondo in continua evoluzione, rendendo concetti complessi accessibili e comprensibili. Sul sito bartolomeoalberico.it, mi impegno a fornire contenuti accurati e aggiornati, verificando le informazioni e organizzandole in modo chiaro per offrire una guida utile e affidabile.

Scrivi un commento