Por que o Python está executando meu módulo quando eu o importo e como eu o paro?

173

Estou desenvolvendo um programa Python que pode ser executado de duas maneiras: a primeira é chamar "python main.py", que solicita a entrada do usuário de maneira amigável e, em seguida, executa a entrada do usuário por meio do programa. A outra maneira é chamar "python batch.py -file- ", que repassará toda a coleta amigável de entradas e executará o valor de entrada de um arquivo inteiro através do programa de uma só vez.

O problema é que, quando executo "batch.py", ele importa algumas variáveis ​​/ métodos / etc de "main.py" e quando executa esse código:

import main

na primeira linha do programa, ele imediatamente erros porque tenta executar o código em "main.py".

Como posso impedir que o Python execute o código contido no módulo "principal" que estou importando?

Dasmowenator
fonte

Respostas:

251

Porque é assim que o Python funciona - palavras-chave como classe nãodef são declarações . Em vez disso, são declarações reais ao vivo que são executadas. Se eles não fossem executados, seu módulo estaria .. vazio :-)

De qualquer forma, a abordagem idiomática é:

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

Consulte Para que serve if __name__ == "__main__"?

No entanto, requer controle de origem sobre o módulo que está sendo importeditado.

Feliz codificação.


fonte
1
apenas para confirmar, seu comentário "coisas apenas para execução quando não são chamadas via 'import' aqui" implica que os comandos sejam escritos em main (), certo? Ou isso não importa?
Goldname 16/07/19
@Goldname O código dentro da instrução if não será executado quando importado, mas a função principal por si só está definida e pronta para uso mesmo através de uma importação. Este módulo apenas executaria a função principal quando executada, e não a executaria se importada. Tudo depende do que você quer fazer. Se você não precisa dos comandos dentro de main em outro lugar, escreva-os de qualquer maneira dentro do if. Mas para mim parece mais arrumado.
Felix
51

Devido à maneira como o Python funciona, é necessário executar seus módulos quando os importar.

Para impedir que o código no módulo seja executado quando importado, mas apenas quando executado diretamente, você pode protegê-lo com isso if:

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

Você pode colocar esse código em um main()método, para poder executar o arquivo diretamente ou importar o módulo e chamar o main(). Por exemplo, suponha que isso esteja no arquivo foo.py.

def main():
    print "Hello World"

if __name__ == "__main__":
    main()

Este programa pode ser executado indo python foo.pyou a partir de outro script Python:

import foo

...

foo.main()
Jeremy Banks
fonte
12

Use o if __name__ == '__main__'idioma - __name__é uma variável especial cujo valor é '__main__'se o módulo estiver sendo executado como um script e o nome do módulo se for importado. Então você faria algo como

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

Infelizmente você não. Isso faz parte de como a sintaxe de importação funciona e é importante que isso aconteça - lembre- defse de que na verdade é algo executado, se o Python não executasse a importação, você ficaria preso às funções.

Porém, como você provavelmente tem acesso ao arquivo, poderá procurar e ver o que causa o erro. Pode ser possível modificar seu ambiente para impedir que o erro aconteça.

cwallenpoole
fonte
1
Como uma nota: se não há nenhuma maneira de modificar o ambiente para que o erro pode ser evitado, talvez você deve usar um módulo diferente
cwallenpoole
4

Coloque o código dentro de uma função e ele não será executado até que você chame a função. Você deve ter uma função principal no seu main.py. com a declaração:

if __name__ == '__main__':
  main()

Então, se você chamar, python main.pya main()função será executada. Se você importar main.py, não será. Além disso, você provavelmente deve renomear main.pypara outra coisa por uma questão de clareza.

Matt
fonte
3

Havia uma proposta de aprimoramento do Python PEP 299 que visava substituir o if __name__ == '__main__':idioma por def __main__:, mas foi rejeitada. Ainda é uma boa leitura saber o que ter em mente ao usar if __name__ = '__main__':.

Paul Tobias
fonte
2

Você pode escrever seu "main.py" assim:

#!/usr/bin/env python

__all__=["somevar", "do_something"]

somevar=""

def do_something():
    pass #blahblah

if __name__=="__main__":
    do_something()
peixe dourado
fonte
-1

Embora você não possa usar importsem executar o código; existe uma maneira rápida de inserir suas variáveis; usando numpy.savez, que armazena variáveis ​​como matrizes numpy em um arquivo .npz. Depois, você pode carregar as variáveis ​​usando numpy.load.

Veja uma descrição completa na documentação do scipy

Observe que este é apenas o caso de variáveis ​​e matrizes de variáveis, e não de métodos etc.

user3569257
fonte
-4

Tente apenas importar as funções necessárias do main.py? Assim,

from main import SomeFunction

Pode ser que você tenha nomeado uma função em batch.py ​​da mesma forma que uma em main.py, e quando você importa main.py, o programa executa a função main.py em vez da função batch.py; fazendo o acima deve corrigir isso. Eu espero.

Dave Lewis
fonte
Pelo menos no Windows, não.
Martín Coll
2
import mainNÃO importa tudo do main para o namespace atual. Ele adiciona apenas um único mainsímbolo no espaço para nome atual, para que colisões não possam acontecer.
Remor #