¿Por qué Python ejecuta mi módulo cuando lo importo y cómo lo detengo?

173

Tengo un programa Python que estoy construyendo que se puede ejecutar de dos maneras: la primera es llamar a "python main.py", que solicita al usuario que ingrese de manera amigable y luego ejecuta la entrada del usuario a través del programa. La otra forma es llamar a "python batch.py -file- ", que pasará por alto toda la recopilación de entrada amigable y ejecutará todo el archivo de entrada a través del programa de una sola vez.

El problema es que cuando ejecuto "batch.py" importa algunas variables / métodos / etc de "main.py", y cuando ejecuta este código:

import main

en la primera línea del programa, se produce un error inmediato porque intenta ejecutar el código en "main.py".

¿Cómo puedo evitar que Python ejecute el código contenido en el módulo "principal" que estoy importando?

Dasmowenator
fuente

Respuestas:

251

Porque así es como funciona Python: palabras clave como classy nodef son declaraciones . En cambio, son declaraciones reales en vivo que se ejecutan. Si no se ejecutaran, su módulo estaría .. vacío :-)

De todos modos, el enfoque idiomático es:

# stuff to run always here such as class/def
def main():
    pass

if __name__ == "__main__":
   # stuff only to run when not called via 'import' here
   main()

Ver ¿ Para qué sirve if __name__ == "__main__"?

Requiere control de fuente sobre el módulo que se está import editando.

Feliz codificación


fuente
1
solo para confirmar, su comentario "cosas que solo se ejecutarán cuando no se llame a través de 'importar' aquí" implica que los comandos se escribirán en main (), ¿verdad? ¿O no importa?
Goldname
@Goldname El código dentro de la instrucción if no se ejecutará cuando se importe, pero la función principal en sí misma está definida y lista para usar incluso a través de una importación. Este módulo solo ejecuta la función principal cuando se ejecuta, y no la ejecuta si se importa. Todo depende de lo que quieras hacer. Si no necesita los comandos dentro de main en otro lugar, escríbalos dentro del if. Pero para mí se ve más ordenado.
Felix
51

Debido a la forma en que funciona Python, es necesario que ejecute sus módulos cuando los importa.

Para evitar que se ejecute código en el módulo cuando se importa, pero solo cuando se ejecuta directamente, puede protegerlo con esto if:

if __name__ == "__main__":
    # this won't be run when imported

Es posible que desee poner este código en un main()método, de modo que pueda ejecutar el archivo directamente o importar el módulo y llamar al main(). Por ejemplo, suponga que esto está en el archivo foo.py.

def main():
    print "Hello World"

if __name__ == "__main__":
    main()

Este programa se puede ejecutar yendo python foo.pyo desde otro script de Python:

import foo

...

foo.main()
Jeremy Banks
fuente
12

Use el if __name__ == '__main__'idioma: __name__es una variable especial cuyo valor es '__main__'si el módulo se está ejecutando como un script, y el nombre del módulo si se importa. Entonces harías algo como

# imports
# class/function definitions
if __name__ == '__main__':
    # code here will only run when you invoke 'python main.py'
Ismail Badawi
fuente
4

Lamentablemente no. Eso es parte de cómo funciona la sintaxis de importación y es importante que lo haga, recuerdedef que en realidad es algo ejecutado, si Python no ejecutó la importación, estaría, bueno, atascado sin funciones.

Sin embargo, dado que probablemente tenga acceso al archivo, es posible que pueda ver y ver qué causa el error. Es posible que pueda modificar su entorno para evitar que ocurra el error.

cwallenpoole
fuente
1
Como nota: si no hay forma de modificar el entorno para evitar el error, tal vez debería usar un módulo diferente
cwallenpoole
4

Ponga el código dentro de una función y no se ejecutará hasta que llame a la función. Deberías tener una función principal en tu main.py. con la declaración:

if __name__ == '__main__':
  main()

Entonces, si llamas python main.py la main()función se ejecutará. Si importa main.py, no lo hará. Además, probablemente debería cambiar el nombre main.pya otra cosa por razones de claridad.

Mate
fuente
3

Hubo una propuesta de mejora de Python PEP 299 que tenía como objetivo reemplazar la if __name__ == '__main__':expresión idiomática def __main__:, pero fue rechazada. Todavía es una buena lectura saber qué tener en cuenta al usar if __name__ = '__main__':.

Paul Tobias
fuente
2

Puede escribir su "main.py" de esta manera:

#!/usr/bin/env python

__all__=["somevar", "do_something"]

somevar=""

def do_something():
    pass #blahblah

if __name__=="__main__":
    do_something()
pez dorado
fuente
-1

Aunque no puede usar importsin ejecutar el código; hay una manera bastante rápida de ingresar sus variables; mediante el uso numpy.savez, que almacena variables como matrices numpy en un archivo .npz. Luego puede cargar las variables usando numpy.load.

Vea una descripción completa en la documentación scipy

Tenga en cuenta que este es solo el caso para variables y matrices de variables, y no para métodos, etc.

usuario3569257
fuente
-4

¿Intenta importar las funciones necesarias desde main.py? Entonces,

from main import SomeFunction

Puede ser que haya nombrado una función en batch.py ​​igual que una en main.py, y cuando importa main.py el programa ejecuta la función main.py en lugar de la función batch.py; hacer lo anterior debería arreglar eso. Espero.

Dave Lewis
fuente
Al menos en Windows, no lo hace.
Martín Coll
2
import mainNO importa todo, desde main al espacio de nombres actual. Solo agrega un solo mainsímbolo en el espacio de nombres actual, por lo que no pueden ocurrir colisiones.
Remram