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.