En esta guía, comprenderá la funcionalidad y la importancia de si __nombre__ == '__principal__' en Python.

¿Alguna vez ha hojeado un código base de Python con diferentes módulos?

En caso afirmativo, probablemente se haya encontrado con if __name__ == '__main__' condicional en uno o más módulos. En los próximos minutos, desmitificaremos lo que significa el condicional anterior y veremos un ejemplo en el que puede ser útil.

Vamos a empezar!

¿Cuál es el significado de __name__ en Python?

¿Cuál es el significado de __name__ en Python?

In Python, un módulo es un py archivo que contiene definiciones de funciones, un conjunto de expresiones para evaluar y más. Por ejemplo, si tenemos un archivo llamado hello_world.py, nos referiremos a este como el archivo hello_world.py o el hello_world módulo.

Cuando ejecuta un módulo de Python, el Intérprete de Python establece los valores de algunas variables especiales antes de la ejecución: __name__ es uno de ellos. La clave para entender el significado   __name__ es comprender cómo funcionan las importaciones en Python.

📁 Descarga el código de esta sección aquí.

Dirígete a la carpeta example-1. tenemos el archivo module1.py. Las __name__ La variable está en el espacio de nombres del módulo actual.

Este módulo imprime una línea seguida del valor del __name__ variable.

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

Ahora, vamos a correr module1 desde la linea de comando

$ python module1.py

En la salida, vemos que el __name__ la variable está configurada para __main__.

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

Importación de módulos en Python

Además de ejecutar un módulo de Python, es posible que a veces desee utilizar la funcionalidad de otro módulo de Python dentro del módulo actual. Python facilita esto a través de importaciones.

Las importaciones le permiten reutilizar la funcionalidad de otro módulo, al importarlo al alcance del módulo actual, sin tener que volver a escribir el código.

Importación de módulos en Python

El module2.py archivo contiene lo siguiente. hemos importado module1 interior. module2.

# example-1/module2.py

import module1 # module1 is imported

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

Corremos module2.py y observe la salida.

$ python module2.py

En la salida a continuación:

  • Vemos eso module1 se ejecuta bajo el capó cuando lo importamos dentro module2y se imprime la salida correspondiente.
  • Pero esta vez, la variable __name__ no es __main__ sino module1.
  • porque corrimos module2 directamente, la variable __name__ correspondiente al módulo ahora es __main__.
Output

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

???? Idea clave:

– Si un módulo se ejecuta directamente, su variable __name__ se establece en es igual a __principal__

– Si un módulo se importa dentro de otro módulo, su __nombre__ se establece en el nombre del modulo.

Ejemplo de if __name__=='__main__' en Python

Ejemplo de if __name__=='__main__' en Python

En la sección, veremos un caso de uso práctico del condicional if __name__ == '__main__'. Definiremos una función simple y luego escribiremos pruebas unitarias para verificar si la función funciona como se esperaba.

📁 Descarga el código y síguelo.

El código de esta sección se encuentra en el example-2 carpeta.

Aquí, add.py es un archivo de Python que contiene la definición de la función add_ab().La función add_ab() toma dos números cualesquiera y devuelve su suma.

# example-2/add.py

def add_ab(a,b):
    return a + b
prueba de unidad

Usaremos Python unittest módulo para probar la función add_ab().

Escribir casos de prueba para una función de Python

Mire el fragmento de código a continuación, que contiene el contenido de la test_add módulo.

# 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)
    

El código anterior hace lo siguiente:

  • Importa Python incorporado prueba de unidad módulo
  • Importa la función add_ab() from the add módulo
  • Define la clase de prueba TestAdd y un conjunto de casos de prueba como métodos dentro de la clase de prueba

Para configurar pruebas unitarias para su código, primero debe definir una clase de prueba que herede de unittest.TestCase. Todos los casos de prueba deben especificarse como métodos dentro de la clase y deben comenzar con test_.

Nota:: Si no nombra los métodos como test_<some-descriptive-name>, verá que las pruebas correspondientes no se detectarán y, por lo tanto, no se ejecutarán.

Ahora intentemos ejecutar el test_add módulo de la terminal.

$ python test_add.py

Verá que no hay resultados y que ninguna de las pruebas se ha ejecutado.

¿Por qué es este el caso?🤔

Esto se debe a que para ejecutar las pruebas unitarias, debe ejecutar unittest como el módulo principal mientras se ejecuta test_add.py, usando el siguiente comando.

$ python -m unittest test_add.py

Al ejecutar el comando detallado anterior, vemos que las tres pruebas se ejecutaron correctamente.

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

OK

Sin embargo, será conveniente ejecutar las pruebas cuando este módulo test_add se ejecuta, ¿sí? Aprendamos cómo hacerlo en la siguiente sección.

Usar if __name__ == '__main__' para ejecutar unittest como módulo principal

Ejecute unittest como el módulo principal

Si desea ejecutar todas las pruebas unitarias cuando el módulo se ejecuta directamente, puede agregar el condicional.

# 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()

El condicional en el fragmento de código anterior le dice al intérprete de Python: Si este módulo se ejecuta directamente, ejecute el código que contiene. unittest.main().

Puede ejecutar el test_add módulo después de agregar las dos líneas de código anteriores.

$ python test_add.py

▶️ Ejecutar el módulo de agregar prueba directamente ahora ejecuta las tres pruebas que hemos definido.

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

OK

El resultado OK anterior indica que todas las pruebas se ejecutaron con éxito. Los tres puntos... indican que se realizaron tres pruebas y todas pasaron.

Ahora, cambiemos el valor de retorno esperado test_add_1_minus7 a 8. Debido a que la función devuelve – 6 en este caso, debería haber una prueba fallida.

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

Como se ve en la salida a continuación, obtenemos .F., de las tres pruebas, el patrón de una de ellas falló (la segunda prueba), y en el rastreo, obtenemos un AssertionError indicando – 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 a tener en cuenta es que las pruebas no necesariamente se ejecutan en el mismo orden en que se especifican en la clase de prueba. En el ejemplo anterior, test_add_1_minus7 se define como el tercer método en la clase de prueba, pero la prueba correspondiente se ejecutó en segundo lugar.

Recapitulación

Espero que este tutorial te haya ayudado a comprender cómo funciona el condicional if __name__ == '__main__' en Python. 

Aquí hay un resumen rápido de los puntos clave:

  • El intérprete de Python establece el __nombre__ variable antes de ejecutar el script de Python.
  • Cuando ejecuta un módulo directamente, el valor del __nombre__ is __principal__.
  • Cuando importa un módulo dentro de otra secuencia de comandos de Python, el valor de la __nombre__ es el nombre del módulo.
  • Puedes usar si __nombre__ == '__principal__' para controlar la ejecución y qué partes del módulo se ejecutan durante las ejecuciones directas e importadas, respectivamente.

A continuación, consulte esta guía detallada sobre Conjuntos de Python. ¡Feliz aprendizaje!🎉