[python] ¿Qué hace si __name__ == "__main__": do?


Answers

Cuando su script se ejecuta pasándolo como un comando al intérprete de Python,

python myscript.py

todo el código que está en el nivel de sangría 0 se ejecuta. Las funciones y las clases definidas están bien definidas, pero no se ejecuta ninguno de sus códigos. A diferencia de otros idiomas, no hay una función main() que se ejecute automáticamente: la función main() es implícitamente todo el código en el nivel superior.

En este caso, el código de nivel superior es un bloque if . __name__ es una variable incorporada que evalúa el nombre del módulo actual. Sin embargo, si un módulo se está ejecutando directamente (como en myscript.py arriba), entonces __name__ lugar se establece en la cadena "__main__" . Por lo tanto, puede probar si su script se está ejecutando directamente o si se está importando por algo más mediante la prueba

if __name__ == "__main__":
    ...

Si su script se está importando a otro módulo, se importarán sus diversas definiciones de funciones y clases y se ejecutará su código de nivel superior, pero el código en el cuerpo de la cláusula if anterior no se ejecutará como condición. no se cumple Como ejemplo básico, considere los siguientes dos scripts:

# file one.py
def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
# file two.py
import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")

Ahora, si invocas al intérprete como

python one.py

La salida será

top-level in one.py
one.py is being run directly

Si ejecuta two.py en two.py lugar:

python two.py

Usted obtiene

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

Por lo tanto, cuando se carga el módulo one , su __name__ equivale a "one" lugar de "__main__" .

Question

¿Qué hace el if __name__ == "__main__": do?

# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
    while True:
        lock.acquire()
        time.sleep(sleeptime)
        lock.release()
        time.sleep(sleeptime)

if __name__ == "__main__":
    lock = thread.allocate_lock()
    thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
    thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))



Hay una serie de variables que el sistema (intérprete de Python) proporciona para los archivos fuente (módulos). Puedes obtener sus valores cuando lo desees, así que centrémonos en la variable / atributo __name__ :

Cuando Python carga un archivo de código fuente, ejecuta todo el código encontrado en él. (Tenga en cuenta que no llama a todos los métodos y funciones definidos en el archivo, pero sí los define).

Sin embargo, antes de que el intérprete ejecute el archivo de código fuente, define algunas variables especiales para ese archivo; __name__ es una de esas variables especiales que Python define automáticamente para cada archivo de código fuente.

Si Python está cargando este archivo de código fuente como el programa principal (es decir, el archivo que ejecuta), establece la variable especial __name__ para que este archivo tenga un valor "__main__" .

Si esto se está importando desde otro módulo, __name__ se establecerá en el nombre de ese módulo.

Entonces, en tu ejemplo en parte:

if __name__ == "__main__":
   lock = thread.allocate_lock()
   thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
   thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

significa que el bloque de código:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

se ejecutará solo cuando ejecute el módulo directamente; el bloque de código no se ejecutará si otro módulo lo está llamando / importando porque el valor de __name__ no será igual a " principal " en esa instancia particular.

Espero que esto ayude.




Puede hacer que el archivo se pueda utilizar como script y como módulo importable .

fibo.py (un módulo llamado fibo )

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Referencia: https://docs.python.org/3.5/tutorial/modules.html




if __name__ == "__main__":
    main()

Comprueba si el atributo __name__ de la secuencia de comandos python es "__main__" . En otras palabras, si se ejecuta el programa en sí, el atributo será __main__ , por lo que se ejecutará el programa (en este caso, la función main() ).

Sin embargo, si el script de python es utilizado por un módulo, se ejecutará cualquier código fuera de la instrucción if , por lo que if \__name__ == "\__main__" se usa solo para verificar si el programa se usa como módulo o no, y por lo tanto, decide si ejecutar el código.




¿Qué hace el if __name__ == "__main__": do?

Para delinear los conceptos básicos:

  • La variable global, __name__ , en el módulo que es el punto de entrada a su programa, es '__main__' . De lo contrario, es el nombre por el que importa el módulo.

  • Entonces, el código debajo del bloque if solo se ejecutará si el módulo es el punto de entrada a su programa.

  • Permite que el código en el módulo sea importable por otros módulos, sin ejecutar el bloque de código debajo de la importación.

¿Porqué necesitamos esto?

Desarrollando y probando su código

Digamos que está escribiendo un script de Python diseñado para ser utilizado como un módulo:

def do_important():
    """This function does something very important"""

Puede probar el módulo agregando esta llamada de la función al final:

do_important()

y ejecutarlo (en un símbolo del sistema) con algo como:

~$ python important.py

El problema

Sin embargo, si desea importar el módulo a otro script:

import important

En la importación, se do_important función do_important , por lo que probablemente comentaría su llamada a la función, do_important() , en la parte inferior.

# do_important() # I must remember to uncomment to execute this!

Y luego tendrá que recordar si ha comentado o no su llamada a la función de prueba. Y esta complejidad adicional significaría que es probable que lo olvides, haciendo que tu proceso de desarrollo sea más problemático.

Una mejor manera

La variable __name__ apunta al espacio de nombres dondequiera que esté el intérprete de Python en este momento.

Dentro de un módulo importado, es el nombre de ese módulo.

Pero dentro del módulo primario (o una sesión interactiva de Python, es decir, la lectura, evaluación, bucle de impresión o REPL) del intérprete, está ejecutando todo desde su "__main__" .

Entonces, si comprueba antes de ejecutar:

if __name__ == "__main__":
    do_important()

Con lo anterior, su código solo se ejecutará cuando lo esté ejecutando como el módulo principal (o lo llame intencionalmente desde otro script).

Una forma aún mejor

Sin embargo, hay una forma pitónica de mejorar en esto.

¿Qué sucede si queremos ejecutar este proceso de negocio desde fuera del módulo?

Si ponemos el código que queremos ejercer a medida que desarrollamos y probamos en una función como esta y luego hacemos nuestro chequeo de '__main__' inmediatamente después:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

Ahora tenemos una función final para el final de nuestro módulo que se ejecutará si ejecutamos el módulo como el módulo principal.

Permitirá que el módulo y sus funciones y clases se importen a otros scripts sin ejecutar la función main , y también permitirá que el módulo (y sus funciones y clases) se '__main__' cuando se ejecute desde un módulo diferente '__main__' , es decir,

import important
important.main()

Este modismo también se puede encontrar en la documentación de Python en una explicación del módulo __main__ . Ese texto dice:

Este módulo representa el alcance (por lo demás anónimo) en el que se ejecuta el programa principal del intérprete: comandos leídos desde la entrada estándar, desde un archivo de script o desde un indicador interactivo. Es este entorno en el que la estrofa idiomática "script condicional" hace que se ejecute un script:

if __name__ == '__main__':
    main()



¿Qué hace if __name__ == "__main__": do?

__name__ es una variable global (en Python, global significa realmente en el nivel de módulo ) que existe en todos los espacios de nombres. Por lo general, es el nombre del módulo (como un tipo str ).

Como el único caso especial, sin embargo, en cualquier proceso de Python que ejecutes, como en mycode.py:

python mycode.py

al espacio de nombre global que de lo contrario es anónimo se le asigna el valor de '__main__' a su __name__ .

Por lo tanto, incluidas las últimas líneas

if __name__ == '__main__':
    main()
  • al final de su script mycode.py,
  • cuando es el módulo principal de punto de entrada ejecutado por un proceso de Python,

hará que se ejecute la función main definida de manera única.

Otro beneficio de usar esta construcción: también puede importar su código como un módulo en otra secuencia de comandos y luego ejecutar la función principal si y cuando su programa decide:

import mycode
# ... any amount of other code
mycode.main()



si nombre == ' principal ':

Vemos si __name__ == '__main__' : con bastante frecuencia.

Comprueba si un módulo se está importando o no.

En otras palabras, el código dentro del bloque if se ejecutará solo cuando el código se ejecute directamente. Aquí directly significa not imported .

Veamos qué hace usando un código simple que imprime el nombre del modue:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

Si ejecutamos el código directamente a través de python test.py , el nombre del módulo es __main__ :

call test()
test module name=__main__



Antes de explicar algo sobre if __name__ == '__main__' , es importante entender qué es __name__ y qué hace.

¿Qué es __name__ ?

__name__ es un DunderAlias ​​- se puede considerar como una variable global (accesible desde módulos) y funciona de manera similar a global .

Es una cadena (global como se mencionó anteriormente) como se indica por type(__name__) (rindiendo <class 'str'> ), y es un estándar incorporado para las versiones de Python 3 y Python 2 .

Dónde:

No solo se puede usar en scripts, sino que también se puede encontrar tanto en el intérprete como en los módulos / paquetes.

Interprete:

>>> print(__name__)
__main__
>>>

Guión:

test_file.py :

print(__name__)

Como resultado __main__

Módulo o paquete:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

Resultando en un somefile

Tenga en cuenta que cuando se usa en un paquete o módulo, __name__ toma el nombre del archivo. La ruta del módulo o ruta del paquete no está dada, pero tiene su propio DunderAlias __file__ , que permite esto.

Debería ver que, donde __name__ , donde es el archivo principal (o programa) siempre devolverá __main__ , y si es un módulo / paquete, o cualquier cosa que se esté ejecutando en algún otro script de Python, devolverá el nombre del archivo de dónde se originó.

Práctica:

Ser una variable significa que su valor puede sobrescribirse ("can" no significa "should"), sobrescribir el valor de __name__ dará como resultado una falta de legibilidad. Entonces no lo hagas, por cualquier razón. Si necesita una variable, defina una nueva variable.

Siempre se asume que el valor de __name__ es __main__ o el nombre del archivo. Una vez más, cambiar este valor predeterminado causará más confusión de que funcionará, causando problemas más adelante en la línea.

ejemplo:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

En general, se considera una buena práctica incluir el if __name__ == '__main__' en las secuencias de comandos.

Ahora para responder if __name__ == '__main__' :

Ahora sabemos que el comportamiento de __name__ vuelve más claro:

Un if es una instrucción de control de flujo que contiene el bloque de código se ejecutará si el valor dado es verdadero. Hemos visto que __name__ puede tomar __main__ o el nombre del archivo desde el que se importó.

Esto significa que si __name__ es igual a __main__ entonces el archivo debe ser el archivo principal y realmente debe estar ejecutándose (o es el intérprete), no un módulo o paquete importado en el script.

Si de hecho __name__ toma el valor de __main__ se __main__ lo que esté en ese bloque de código.

Esto nos dice que si el archivo que se ejecuta es el principal (o se está ejecutando directamente desde el intérprete), entonces esa condición se debe ejecutar. Si es un paquete, entonces no debería, y el valor no será __main__ .

Módulos:

__name__ también se puede usar en módulos para definir el nombre de un módulo

Variantes:

También es posible hacer otras cosas menos comunes pero útiles con __name__ , algunas mostraré aquí:

Ejecutando solo si el archivo es un módulo o paquete:

if __name__ != '__main__':
    # Do some useful things 

Ejecutando una condición si el archivo es el principal y otro si no lo es:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

También puede usarlo para proporcionar funciones / utilidades de ayuda ejecutables en paquetes y módulos sin el uso elaborado de bibliotecas.

También permite que los módulos se ejecuten desde la línea de comandos como scripts principales, que también pueden ser muy útiles.




Hay muchas cosas diferentes aquí sobre la mecánica del código en cuestión, el "cómo", pero para mí nada de eso tenía sentido hasta que entendí el "por qué". Esto debería ser especialmente útil para los nuevos programadores.

Lleve el archivo "ab.py":

def a():
    print('A function in ab file');
a()

y un segundo archivo "xy.py":

import ab
def main():
    print('main function: this is where the action is')
def x(): 
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

¿Qué está haciendo realmente este código?

Cuando ejecuta xy.py , import ab . La instrucción de importación ejecuta el módulo inmediatamente en la importación, por lo que las operaciones de ab se ejecutan antes del resto de xy . Una vez terminado con ab , continúa con xy .

El intérprete realiza un seguimiento de qué scripts se están ejecutando con __name__ . Cuando ejecuta un script, sin importar cómo lo haya llamado, el intérprete lo llama "__main__" , lo que lo convierte en el script principal o 'home' al que se devuelve después de ejecutar un script externo. Cualquier otro script que se llame desde este "__main__" se le asigna su nombre de archivo como su __name__ (por ejemplo, __name__ == "ab.py" ). Por lo tanto, la línea if __name__ == "__main__": es la prueba del intérprete para determinar si está interpretando / analizando la secuencia de comandos 'inicio' que se ejecutó inicialmente, o si se está mirando furtivamente a otra secuencia de comandos (externa). Esto le da al programador flexibilidad para que el script se comporte de manera diferente si se ejecuta directamente frente a llamado externamente.

Avancemos el código anterior para comprender lo que está sucediendo, centrándonos primero en las líneas no perdidas y el orden en que aparecen en los guiones. Recuerde que la función - o def - bloques no hacen nada por sí mismos hasta que son llamados. Lo que el intérprete podría decir si murmurara para sí mismo:

  • Abra xy.py como el archivo 'home'; llámalo "__main__" en la variable __name__ .
  • Importe y abra el archivo con __name__ == "ab.py" .
  • Oh, una función. Recordaré eso.
  • Ok, función a() ; Me acabo de enterar de eso. Imprimir ' Una función en un archivo ab '.
  • Fin del documento; volver a "__main__" !
  • Oh, una función. Recordaré eso.
  • Otro.
  • Función x() ; ok, imprimiendo ' tareas periféricas: podría ser útil en otros proyectos '.
  • ¿Qué es esto? Una declaración if . Bueno, la condición se ha cumplido (la variable __name__ se ha establecido en "__main__" ), así que ingresaré en la función main() e imprimiré la ' función principal: aquí es donde está la acción '.

Las dos líneas inferiores significan: "Si este es el script main o 'home', ejecute la función llamada main() ". Es por eso que verá un def main(): block up top, que contiene el flujo principal de la funcionalidad del script.

¿Por qué implementar esto?

¿Recuerdas lo que dije antes sobre las declaraciones de importación? Cuando importa un módulo, no solo lo "reconoce" y espera más instrucciones, sino que ejecuta todas las operaciones ejecutables contenidas en el script. Por lo tanto, poner la carne de su script en la función main() efectivamente lo pone en cuarentena, poniéndolo en forma aislada para que no se ejecute inmediatamente cuando lo importe otro script.

De nuevo, habrá excepciones, pero la práctica común es que main() no suele llamarse externamente. Así que te estarás preguntando una cosa más: si no estamos llamando a main() , ¿por qué llamamos al script? Se debe a que muchas personas estructuran sus scripts con funciones independientes que están diseñadas para ejecutarse independientemente del resto del código en el archivo. Posteriormente, se les llama a otro lugar en el cuerpo del guión. Lo que me lleva a esto:

Pero el código funciona sin él

Si, eso es correcto Estas funciones separadas pueden invocarse desde un script en línea que no está contenido dentro de una función main() . Si está acostumbrado (como lo estoy yo, en mis primeros pasos de programación) a crear scripts en línea que hagan exactamente lo que necesita, y tratará de resolverlo nuevamente si alguna vez necesita esa operación nuevamente. Bueno, no está acostumbrado a este tipo de estructura interna en su código, porque es más complicado de construir y no es tan intuitivo de leer. Pero ese es un script que probablemente no pueda tener sus funciones llamadas externamente, porque si lo hiciera, comenzaría a calcular y asignar variables inmediatamente. Y lo más probable es que si intenta volver a utilizar una función, su nueva secuencia de comandos esté relacionada con la anterior de forma tal que haya variables conflictivas.

Al dividir las funciones independientes, obtiene la capacidad de reutilizar su trabajo anterior llamándolos a otro script. Por ejemplo, "example.py" podría importar "xy.py" y llamar a x() , haciendo uso de la función "x" de "xy.py". (Tal vez está capitalizando la tercera palabra de una cadena de texto dada, creando una matriz numpy a partir de una lista de números y cuadratándola, o degenerando una superficie 3D. Las posibilidades son ilimitadas).

[Como un aparte, este hilo contiene una respuesta de @kindall que finalmente me ayudó a entender: el Por qué, no el Cómo. Lamentablemente se ha marcado como duplicado de este , lo que creo que es un error.]




if __name__ == "__main__": es básicamente un entorno de script de nivel superior, especifica el intérprete que ('Tengo la prioridad más alta para ejecutar primero').

'__main__' es el nombre del ámbito en el que se ejecuta el código de nivel superior. El __name__ un módulo se establece igual a '__main__' cuando se lee desde la entrada estándar, un script o desde un indicador interactivo.

if __name__ == "__main__":
    # execute only if run as a script
    main()



Cuando ejecuta Python interactivamente, a la variable __name__ local se le asigna un valor de __main__ . Del mismo modo, cuando ejecuta un módulo de Python desde la línea de comandos, en lugar de importarlo a otro módulo, a su atributo __name__ se le asigna un valor de __main__ , en lugar del nombre real del módulo. De esta forma, los módulos pueden ver su propio valor __name__ para determinar por sí mismos cómo se usan, ya sea como soporte para otro programa o como la aplicación principal ejecutada desde la línea de comando. Por lo tanto, la siguiente expresión es bastante común en los módulos de Python:

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.



Related