Perché Python esegue il mio modulo al momento dell'importazione e come posso interromperlo?


173

Ho un programma Python che sto costruendo che può essere eseguito in uno dei due modi: il primo è chiamare "python main.py" che richiede all'utente un input in modo amichevole e quindi esegue l'input dell'utente attraverso il programma. L'altro modo è quello di chiamare "python batch.py -file- " che passerà su tutta la raccolta di input amichevole ed eseguirà l'intero valore del file di input attraverso il programma in una sola volta.

Il problema è che quando eseguo "batch.py" importa alcune variabili / metodi / etc da "main.py" e quando esegue questo codice:

import main

alla prima riga del programma, si guasta immediatamente perché tenta di eseguire il codice in "main.py".

Come posso impedire a Python di eseguire il codice contenuto nel modulo "principale" che sto importando?

Risposte:


251

Perché è così che funziona Python: parole chiave come classe nondef sono dichiarazioni . Invece, sono vere dichiarazioni dal vivo che vengono eseguite. Se non fossero stati eseguiti, il tuo modulo sarebbe .. vuoto :-)

Comunque, l'approccio idiomatico è:

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

Vedi A cosa serve if __name__ == "__main__"?

importTuttavia, richiede il controllo del codice sorgente sul modulo in fase di modifica .

Buona codifica.


1
solo per confermare, il tuo commento "roba da eseguire solo quando non viene chiamato tramite 'import' qui" implica i comandi da scrivere sotto main (), giusto? O non importa ??
Goldname

@Goldname Il codice all'interno dell'istruzione if non verrà eseguito durante l'importazione, ma la funzione principale in sé è definita e pronta per l'uso anche attraverso un'importazione. Questo modulo eseguirà semplicemente la funzione principale quando viene eseguito e non eseguirla se importata. Tutto dipende da cosa vuoi fare. Se non hai bisogno dei comandi all'interno di main altrove, scriverli sicuramente all'interno dell'if. Ma per me sembra più ordinato.
Felix,

51

A causa del modo in cui Python funziona, è necessario che esegua i moduli quando li importa.

Per impedire l'esecuzione del codice nel modulo durante l'importazione, ma solo quando eseguito direttamente, è possibile proteggerlo con questo if:

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

Potresti voler inserire questo codice in un main()metodo, in modo da poter eseguire direttamente il file o importare il modulo e chiamare il main(). Ad esempio, supponiamo che questo sia nel file foo.py.

def main():
    print "Hello World"

if __name__ == "__main__":
    main()

Questo programma può essere eseguito andando python foo.pyo da un altro script Python:

import foo

...

foo.main()

12

Usa il if __name__ == '__main__'linguaggio: __name__è una variabile speciale il cui valore è '__main__'se il modulo viene eseguito come script e il nome del modulo se viene importato. Quindi faresti qualcosa del genere

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

4

Sfortunatamente no. Questo è parte del modo in cui funziona la sintassi di importazione ed è importante che lo faccia - ricorda che in defrealtà è qualcosa di eseguito, se Python non eseguisse l'importazione, saresti, beh, bloccato senza funzioni.

Dato che probabilmente hai accesso al file, tuttavia, potresti essere in grado di cercare e vedere quali sono le cause dell'errore. Potrebbe essere possibile modificare il proprio ambiente per evitare che si verifichi l'errore.


1
Come nota: se non c'è modo di modificare l'ambiente in modo che l'errore possa essere prevenuto, forse dovresti usare un modulo diverso
cwallenpoole,

4

Inserisci il codice all'interno di una funzione e non verrà eseguito fino a quando non chiamerai la funzione. Dovresti avere una funzione principale nel tuo main.py. con l'affermazione:

if __name__ == '__main__':
  main()

Quindi, se si chiama, python main.pyla main()funzione verrà eseguita. Se si importa main.py, non lo farà. Inoltre, dovresti probabilmente rinominare main.pyqualcos'altro per motivi di chiarezza.


3

C'era una proposta di potenziamento di Python PEP 299 che mirava a sostituire il if __name__ == '__main__':linguaggio con def __main__:, ma è stato respinto. È comunque una buona lettura sapere cosa tenere a mente durante l'utilizzo if __name__ = '__main__':.


2

Puoi scrivere il tuo "main.py" in questo modo:

#!/usr/bin/env python

__all__=["somevar", "do_something"]

somevar=""

def do_something():
    pass #blahblah

if __name__=="__main__":
    do_something()

-1

Sebbene non sia possibile utilizzare importsenza eseguire il codice; c'è un modo abbastanza rapido in cui puoi inserire le tue variabili; usando numpy.savez, che memorizza le variabili come array numpy in un file .npz. Successivamente è possibile caricare le variabili utilizzando numpy.load.

Vedi una descrizione completa nella documentazione di Scipy

Si noti che questo è solo il caso di variabili e matrici di variabili, non di metodi, ecc.


-4

Prova a importare solo le funzioni necessarie da main.py? Così,

from main import SomeFunction

È possibile che tu abbia chiamato una funzione in batch.py ​​uguale a una in main.py e quando importi main.py il programma esegue la funzione main.py invece della funzione batch.py; fare quanto sopra dovrebbe risolverlo. Io spero.


Almeno su Windows, non lo è.
Martín Coll,

2
import mainNON importa tutto da main nello spazio dei nomi corrente. Aggiunge solo un singolo mainsimbolo nello spazio dei nomi corrente, quindi non possono verificarsi collisioni.
remram,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.