Capire se __name__ == ‘__main__’ in Python

In questa guida, capirai la funzionalità e il significato di if __name__ == ‘__main__’ in Python.

Hai mai sfogliato una base di codice Python con moduli diversi?

Se sì, probabilmente ti saresti imbattuto se __name__ == ‘__main__’ fosse condizionale in uno o più moduli. Nei prossimi minuti, demistificare il significato del condizionale di cui sopra e guardare un esempio in cui può essere utile.

Cominciamo!

Qual è il significato di __name__ in Python?

In Python, un modulo è un file .py che contiene definizioni di funzioni, un insieme di espressioni da valutare e altro. Ad esempio, se abbiamo un file chiamato hello_world.py, lo chiamiamo file hello_world.py o modulo hello_world.

Quando esegui un modulo Python, l’interprete Python imposta i valori per alcune variabili speciali prima dell’esecuzione: __name__ è uno di questi. La chiave per comprendere il significato di __name__ è capire come funzionano le importazioni in Python.

📁 Scarica qui il codice di questa sezione.

Vai alla cartella esempio-1. Abbiamo il file module1.py. La variabile __name__ si trova nello spazio dei nomi del modulo corrente.

Questo modulo stampa una riga seguita dal valore della variabile __name__.

# example-1/module1.py
print("This is module1.")
print(f"The __name__ variable of module 1 is: {__name__}.")

Ora, eseguiamo module1 dalla riga di comando.

$ python module1.py

Nell’output, vediamo che la variabile __name__ è impostata su __main__.

This is module1.
The __name__ variable of module 1 is: __main__.

Importare moduli in Python

Oltre a eseguire un modulo Python, a volte potresti voler utilizzare la funzionalità di un altro modulo Python all’interno del modulo corrente. Python facilita questo attraverso le importazioni.

Le importazioni consentono di riutilizzare la funzionalità di un altro modulo, importandolo nell’ambito del modulo corrente, senza dover riscrivere il codice.

Il file module2.py contiene quanto segue. Abbiamo importato module1 all’interno. modulo2.

# example-1/module2.py

import module1 # module1 is imported

print(f"This is module2")
print(f"The __name__ variable of module2 is: {__name__}.")

Eseguiamo module2.py e osserviamo l’output.

$ python module2.py

Nell’output di seguito:

  • Vediamo che module1 viene eseguito sotto il cofano quando lo importiamo all’interno di module2 e l’output corrispondente viene stampato.
  • Ma questa volta, la variabile __name__ non è __main__ ma module1.
  • Poiché abbiamo eseguito module2 direttamente, la variabile __name__ corrispondente al modulo è ora __main__.
Output

This is module1.
The __name__ variable of module 1 is: module1.
This is module2
The __name__ variable of module2 is: __main__.

💡 Idea chiave:

– Se un modulo viene eseguito direttamente, la sua variabile __name__ è impostata su uguale a __main__.

– Se un modulo viene importato all’interno di un altro modulo, il suo __name__ viene impostato sul nome del modulo.

Esempio di if __name__==’__main__’ in Python

Nella sezione, vedremo un caso d’uso pratico del condizionale if __name__ == ‘__main__’. Definiremo una funzione semplice e quindi scriveremo unit test per verificare se la funzione funziona come previsto.

📁 Scarica il codice e segui.

Il codice per questa sezione si trova nella cartella esempio-2.

Qui, add.py è un file Python che contiene la definizione della funzione add_ab(). La funzione add_ab() accetta due numeri qualsiasi e ne restituisce la somma.

# example-2/add.py

def add_ab(a,b):
    return a + b

Useremo il modulo unittest di Python per testare la funzione add_ab().

Scrivere casi di test per una funzione Python

Guarda lo snippet di codice di seguito, contenente il contenuto del modulo test_add.

# example-2/test_add.py

import unittest
from add import add_ab

class TestAdd(unittest.TestCase):
    def test_add_23(self):
        self.assertEqual(add_ab(2,3), 5)
    
    def test_add_19(self):
        self.assertEqual(add_ab(1,9), 10)
    
    def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), -6)
    

Il codice sopra fa quanto segue:

  • Importa il modulo unittest integrato di Python
  • Importa la funzione add_ab() dal modulo add
  • Definisce la classe di test TestAdd e una serie di casi di test come metodi all’interno della classe di test

Per impostare gli unit test per il tuo codice, devi prima definire una classe di test che erediti da unittest.TestCase. Tutti i casi di test devono essere specificati come metodi all’interno della classe e devono iniziare con test_.

Nota: se non denomini i metodi come test_, vedrai che i test corrispondenti non verranno rilevati e, pertanto, non verranno eseguiti.

Ora proviamo a eseguire il modulo test_add dal terminale.

$ python test_add.py

Vedrai che non c’è output e nessuno dei test è stato eseguito.

Perché è così?🤔

Questo perché per eseguire gli unit test, dovresti eseguire unittest come modulo principale durante l’esecuzione di test_add.py, usando il comando seguente.

$ python -m unittest test_add.py

Dopo aver eseguito il comando dettagliato sopra, vediamo che tutti e tre i test sono stati eseguiti correttamente.

Output
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

Tuttavia, sarà conveniente eseguire i test quando viene eseguito questo modulo test_add, sì? Impariamo come farlo nella prossima sezione.

Usando if __name__ == ‘__main__’ per eseguire unittest come modulo principale

Se desideri eseguire tutti gli unit test quando il modulo viene eseguito direttamente, puoi aggiungere il condizionale.

# example-2/test_add.py

import unittest
from add import add_ab

class TestAdd(unittest.TestCase):
    def test_add_23(self):
        self.assertEqual(add_ab(2,3), 5)
    
    def test_add_19(self):
        self.assertEqual(add_ab(1,9), 10)
    
    def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), -6)

# Run unittest as the main module
if __name__ == '__main__':
        unittest.main()

Il condizionale nel frammento di codice sopra dice all’interprete Python: se questo modulo viene eseguito direttamente, esegui il codice all’interno. unittest.main().

È possibile eseguire il modulo test_add dopo aver aggiunto le due righe di codice precedenti.

$ python test_add.py

▶️ L’esecuzione diretta del modulo test add ora esegue tutti e tre i test che abbiamo definito.

Output
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

L’output sopra OK indica che tutti i test sono stati eseguiti correttamente. I tre punti… indicano che sono stati eseguiti tre test e tutti sono stati superati.

Ora, cambiamo il valore di ritorno previsto test_add_1_minus7 in 8. Poiché la funzione restituisce – 6 in questo caso, dovrebbe esserci un test non riuscito.

def test_add_1_minus7(self):
        self.assertEqual(add_ab(1,-7), 8)

Come si vede nell’output di seguito, otteniamo .F., dei tre test, il pattern di uno di essi non è riuscito (il secondo test) e nel traceback otteniamo un AssertionError che indica – 6 != 8.

Output
.F.
======================================================================
FAIL: test_add_1_minus7 (__main__.TestAdd)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_add.py", line 12, in test_add_1_minus7
    self.assertEqual(add_ab(1,-7), 8)
AssertionError: -6 != 8

----------------------------------------------------------------------
Ran 3 tests in 0.021s

FAILED (failures=1)

Una cosa importante da notare è che i test non vengono necessariamente eseguiti nello stesso ordine in cui sono specificati nella classe di test. Nell’esempio precedente, test_add_1_minus7 è definito come il terzo metodo nella classe di test, ma il test corrispondente è stato eseguito per secondo.

Riassumendo

Spero che questo tutorial ti abbia aiutato a capire come funziona il condizionale if __name__ == ‘__main__’ in Python.

Ecco un breve riepilogo dei punti chiave da asporto:

  • L’interprete Python imposta la variabile __name__ prima di eseguire lo script Python.
  • Quando esegui direttamente un modulo, il valore di __name__ è __main__.
  • Quando importi un modulo all’interno di un altro script Python, il valore di __name__ è il nome del modulo.
  • È possibile utilizzare if __name__ == ‘__main__’ per controllare l’esecuzione e quali parti del modulo vengono eseguite rispettivamente durante le esecuzioni dirette e importate.

Quindi, dai un’occhiata a questa guida approfondita sui set Python. Buon apprendimento!🎉