Sobre la condición if __name__ == «__main __»: ¿Qué debo hacer?

Respuesta corta

Este es un código repetitivo que evita que el usuario llame accidentalmente al script. Los problemas comunes con la omisión de guardias en las secuencias de comandos son:

  • Si importa un script desprotegido a otro script (por ejemplo) import my_script_without_a_name_eq_main_guard), el último script desencadena la ejecución del primero al importar y utiliza los argumentos de la línea de comandos del segundo script. Casi siempre es un error.
  • Si su secuencia de comandos desprotegida tiene una clase personalizada y la guarda en un archivo pickle, al desmarcarla en otra secuencia de comandos se activará la importación de la secuencia de comandos desprotegida. Los problemas descritos en el punto anterior son los mismos.

Temas relacionados:

Respuesta larga

Para comprender mejor por qué y cómo esto es importante, debe dar un paso atrás y comprender cómo Python inicializa los scripts y cómo los scripts interactúan con el mecanismo de importación del módulo.

Cada vez que el intérprete de Python lee un archivo fuente, hace dos cosas:

  • Define algunas variables especiales como __name__entonces
  • Ejecuta todo el código del archivo.

Veamos cómo funciona y qué tiene que ver contigo __name__ Una verificación común en los scripts de Python.

Código de ejemplo

Usemos un código de muestra ligeramente diferente para ver cómo funcionan las importaciones y los scripts. Supongamos que tiene un archivo con el siguiente nombre: foo.py.

# Suppose this is foo.py.

print("before import")
import math

print("before function_a")
def function_a():
    print("Function A")

print("before function_b")
def function_b():
    print("Function B ".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    function_a()
    function_b()
print("after __name__ guard")

Variables especiales

Cuando el intérprete de Python lee un archivo fuente, primero establece algunas variables especiales. En este caso, __name__ dinero en efectivo.

Si el módulo es el programa principal

Al ejecutar un módulo (archivo fuente) como programa principal, por ejemplo:

python foo.py

El intérprete asigna una cadena codificada "__main__" Llegadas __name__ variable, es decir

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

Cuando un módulo es importado por otro módulo

Por otro lado, suponiendo que el otro módulo sea el programa principal, el módulo se importará. Esto significa que el programa principal o cualquier otro módulo importado por el programa principal tiene una instrucción similar a la siguiente:

# Suppose this is in some other main program.
import foo

El intérprete te encontrará foo.py Asigne un nombre al archivo (y busque otras variaciones), y antes de ejecutar el módulo "foo" De la declaración de importación __name__ variable, es decir

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

Ejecute el código del módulo

Una vez que se establece la variable especial, el intérprete ejecuta todo el código en el módulo, una declaración a la vez. Le recomendamos que abra otra ventana al lado del código de muestra para que pueda seguir esta instrucción.

Cada vez

  1. salida de una cadena "before import" (Sin comillas).
  2. Cargo math Módulo y asignarlo a math..Es lo mismo que reemplazar import math De la siguiente manera (tenga en cuenta) __import__ Una función de Python de bajo nivel que toma una cadena y activa la importación real):
# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. salida de una cadena "before function_a".
  2. lo haré def Bloque, cree un objeto de función, luego asigne este objeto de función a function_a..
  3. salida de una cadena "before function_b".
  4. Ejecutar el segundo def Bloquear y crear otro objeto de función y asignarlo a una variable con nombre function_b..
  5. salida de una cadena "before __name__ guard".

Solo si el módulo es el programa principal

  1. Si el módulo es el programa principal __name__ Definitivamente resuelto "__main__" Llame a estas dos funciones e imprima una cadena "Function A" Cuando "Function B 10.0"..

Solo si el módulo fue importado por otro módulo

  1. ((((En cambio) Si el módulo fue importado por otro programa en lugar del programa principal __name__ Estarán "foo"No "__main__"Saltar if declaración.

Cada vez

  1. salida de una cadena "after __name__ guard" En los dos casos.

Generalizar

En resumen, lo que se imprime en ambos casos es:

# What gets printed if foo is the main program
before import
before function_a
before function_b
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before function_a
before function_b
before __name__ guard
after __name__ guard

¿Por qué funciona así?

Quizás te estés preguntando por qué todo el mundo quiere esto. Bueno, a veces quieres escribir .py El archivo puede ser utilizado como módulo por otros programas o módulos, o puede ejecutarse como el propio programa principal. Ejemplo:

  • El módulo es una biblioteca, pero requiere el modo de secuencia de comandos para ejecutar pruebas unitarias o demostraciones.
  • El módulo solo se usa como programa principal, pero hay pruebas unitarias y el marco de prueba funciona importando .py Cree un archivo similar a un script para realizar funciones de prueba especiales. No intente ejecutar el script solo porque está importando un módulo.
  • El módulo se utiliza principalmente como programa principal, pero también proporciona una API de programador para usuarios avanzados.

Además de estos ejemplos, cuando ejecuta el script en Python, se establecen algunas variables mágicas y se importa el script. es elegante «Ejecutar» un script es un efecto secundario de importar un módulo de script.

Reflexión

  • Pregunta: Puedo tener más de uno __name__ ¿Quieres verificar el bloque? R: Es raro hacer eso, pero el lenguaje no te detiene.
  • Supongamos que contiene: foo2.py..y si dijeras python foo2.py ¿En la línea de comando? ¿Por qué?
# Suppose this is foo2.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

def function_a():
    print("a1")
    from foo2 import function_b
    print("a2")
    function_b()
    print("a3")

def function_b():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    function_a()
    print("m2")
print("t2")
      
  • Ahora entiende lo que sucede si lo eliminas. __name__ registro foo3.py:
# Suppose this is foo3.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

def function_a():
    print("a1")
    from foo3 import function_b
    print("a2")
    function_b()
    print("a3")

def function_b():
    print("b")

print("t1")
print("m1")
function_a()
print("m2")
print("t2")
  • ¿Qué pasa si lo uso como script? ¿Qué tal importarlo como un módulo?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")
    
print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")

Aprende más de python con estos temas:

¿ Te fue útil este artículo ?
⬇️ Ayudame compartiendo para poder llegar a más personas.⬇️

3 comentarios en «Sobre la condición if __name__ == «__main __»: ¿Qué debo hacer?»

  1. ¿Por qué la respuesta corta es siempre la mejor opción? ¡Necesitamos más detalles!

    • No siempre la respuesta corta es la mejor opción. A veces se necesitan más detalles para entender completamente un tema. ¡La profundidad importa! No te conformes con lo superficial, busca la riqueza en la información. ¡Más detalles, por favor!

  2. ¡Creo que la respuesta corta es suficiente! ¿Qué opinan ustedes? 🤔👩‍💻

Los comentarios están cerrados.