Cuando programamos en Python, tarde o temprano nos encontramos con la siguiente sentencia condicional: if __name__ == "__main__"
. En este post vamos a ver qué significa exactamente esta expresión. Pero antes de entrar en materia, comentar que para simplificar la explicación vamos a usar en todo momento el término “módulo” para referirnos a un fichero con código Python y extensión .py
.
Ejecución directa e import de un módulo
Cuando le indicamos al intérprete de Python que ejecute nuestro módulo, internamente se inicializan una serie de variables especiales. Una de ellas se llama __name__
, y a ésta se le asigna el valor __main__
cuando el intérprete ejecuta directamente el código desde nuestro módulo. Para entender bien esto, supongamos que nuestro módulo se llama modulo_a.py
, cuyo contenido es el siguiente:
# modulo_a.py print(__name__)
Al ejecutarlo desde el terminal obtenemos el siguiente resultado:
$ python modulo_a.py __main__
Pero en Python también podemos importar módulos para poder usar sus clases y funciones. Es lo que hacemos al usar sentencias import
. En este caso a la variable __name__
del módulo importado se le asigna como valor el nombre del módulo sin la extensión .py
. Veámoslo con el siguiente ejemplo donde tenemos los módulos modulo_a.py
y modulo_b.py
, cuyos contenidos son los siguientes:
# modulo_a.py print("Nombre del módulo A:", __name__)
# modulo_b.py import modulo_a print("Nombre del módulo B:", __name__)
Al ejecutar el modulo_b
desde el terminal obtenemos lo siguiente:
$ python modulo_b.py Nombre del módulo A: modulo_a Nombre del módulo B: __main__
Comprobando si __name__ es __main__
Una vez comprendido el punto anterior, es fácil llegar a la conclusión que cuando usamos la línea de código if __main__ == "__main__":
, en realidad estamos comprobando si nuestro módulo está siendo ejecutado directamente por el intérprete de Python, o si por el contrario está siendo importado por otro módulo. Es lo que vemos en el siguiente ejemplo, donde los contenidos de modulo_a.py
y modulo_b.py
son:
# modulo_a.py if __name__ == "__main__": print("Nombre del módulo A:", __name__)
# modulo_b.py import modulo_a print("Nombre del módulo B:", __name__)
En este caso, al ejecutar modulo_b.py
obtenemos:
$ python modulo_b.py Nombre del módulo B: __main__
Ahora en el resultado no se imprime el nombre del módulo A. Esto sucede porque aunque ejecutamos modulo_b.py
(el cual importa el modulo_a
), también hemos añadido a modulo_a.py
la condición para comprobar si dicho módulo se está ejecutando directamente.
Para acabar de ilustrar todos estos conceptos, veamos que pasa al ejecutar los siguientes módulos:
# modulo_a.py print("Esto se ejecuta siempre") if __name__ == "__main__": print("Ejecutado directamente") else: print("Ejecutado externamente")
# modulo_b.py import modulo_a
$ python modulo_a.py Esto se ejecuta siempre Ejecutado directamente
$ python modulo_b.py Esto se ejecuta siempre Ejecutado externamente
En este ejemplo vemos que la sentencia print()
al inicio de modulo_a.py
se ejecuta indistintamente de si ejecutamos modulo_a.py
o modulo_b.py
. Por el contrario, las sentencias print()
dentro del bloque if else
de modulo_a.py
se ejecutan en función de qué módulo ejecutemos.
Apunte final
Normalmente, después de la sentencia if __name__ == "main":
hacemos referencia a un método del módulo, tal y como se muestra a continuación:
# modulo_a.py def main(): print("Método main() del módulo A") if __name__ == "__main__": main()
La razón para realizar dicha referencia, en lugar de escribir el código directamente y ahorrarnos un método en nuestro módulo, es que también nos permite ejecutar ese método desde fuera de nuestro módulo. Veámoslo con el siguiente modulo_b.py
a modo de ejemplo:
# modulo_b.py import modulo_a modulo_a.main()
Con este patrón de diseño, el método main()
se ejecuta siempre que ejecutemos directamente modulo_a.py
o siempre que lo hayamos referenciado desde otro módulo:
$ python modulo_a.py Método main() del módulo A
$ python modulo_b.py Método main() del módulo A
Espero que todos estos ejemplos te hayan aclarado cualquier duda que tuvieras con esta sentencia tan común en Python. En caso contrario, no dudes dejarme tu pregunta en la sección de comentarios.