python guard how - Cosa succede se __name__ == "__main__": do?




13 Answers

Quando lo script viene eseguito passandolo come comando all'interprete Python,

python myscript.py

tutto il codice che è a livello di indentazione 0 viene eseguito. Le funzioni e le classi che sono definite sono, beh, definite, ma nessuno dei loro codici viene eseguito. A differenza di altri linguaggi, non esiste una funzione main() che viene eseguita automaticamente - la funzione main() è implicitamente tutto il codice al livello più alto.

In questo caso, il codice di livello superiore è un blocco if . __name__ è una variabile integrata che valuta il nome del modulo corrente. Tuttavia, se un modulo viene eseguito direttamente (come in myscript.py sopra), allora __name__ invece è impostato sulla stringa "__main__" . Pertanto, puoi verificare se il tuo script viene eseguito direttamente o se viene importato da qualcos'altro testando

if __name__ == "__main__":
    ...

Se il tuo script viene importato in un altro modulo, le sue varie funzioni e definizioni di classe verranno importate e il codice di livello superiore verrà eseguito, ma il codice nel corpo della clausola if non verrà eseguito come condizione non è stato raggiunto Come esempio di base, prendi in considerazione i seguenti due script:

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

Ora, se invochi l'interprete come

python one.py

L'output sarà

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

Se invece esegui two.py :

python two.py

Ottieni

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

Quindi, quando il modulo one viene caricato, il suo __name__ equivale a "one" anziché a "__main__" .

to define syntax

Che cosa fa 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))



Che cosa fa if __name__ == "__main__": do?

Per delineare le basi:

  • La variabile globale, __name__ , nel modulo che è il punto di accesso al tuo programma, è '__main__' . Altrimenti, è il nome con cui si importa il modulo.

  • Quindi, il codice sotto il blocco if verrà eseguito solo se il modulo è il punto di accesso al programma.

  • Consente al codice nel modulo di essere importabile da altri moduli, senza eseguire il blocco di codice sottostante all'importazione.

perché ne abbiamo bisogno?

Sviluppare e testare il tuo codice

Dì che stai scrivendo uno script Python progettato per essere usato come modulo:

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

È possibile testare il modulo aggiungendo questa chiamata della funzione in basso:

do_important()

e eseguendolo (al prompt dei comandi) con qualcosa di simile:

~$ python important.py

Il problema

Tuttavia, se si desidera importare il modulo in un altro script:

import important

Durante l'importazione, la funzione do_important verrebbe chiamata, quindi probabilmente commenteresti la tua chiamata di funzione, do_important() , in basso.

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

E poi dovrai ricordare se hai o meno commentato la tua chiamata alla funzione di test. E questa complessità in più significherebbe che probabilmente ti dimenticherai, rendendo più problematico il tuo processo di sviluppo.

Un modo migliore

La variabile __name__ punta allo spazio dei nomi ovunque si trovi l'interprete Python al momento.

All'interno di un modulo importato, è il nome di quel modulo.

Ma all'interno del modulo primario (o in una sessione interattiva di Python, cioè nell'interprete Read, Eval, Print Loop o REPL) si sta eseguendo tutto dal suo "__main__" .

Quindi se controlli prima di eseguire:

if __name__ == "__main__":
    do_important()

Con quanto sopra, il tuo codice verrà eseguito solo quando lo stai eseguendo come modulo principale (o intenzionalmente lo chiamerai da un altro script).

Un modo ancora migliore

C'è un modo pitone per migliorare su questo, però.

Cosa succede se vogliamo eseguire questo processo aziendale dall'esterno del modulo?

Se inseriamo il codice che vogliamo esercitare man mano che sviluppiamo e '__main__' in una funzione come questa '__main__' immediatamente il controllo per '__main__' :

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

Ora abbiamo una funzione finale per la fine del nostro modulo che verrà eseguita se eseguiremo il modulo come modulo primario.

Permetterà al modulo e alle sue funzioni e classi di essere importati in altri script senza eseguire la funzione main , e permetterà anche al modulo (e alle sue funzioni e classi) di essere chiamato quando si esegue da un diverso modulo '__main__' , cioè

import important
important.main()

Questo idioma può anche essere trovato nella documentazione di Python in una spiegazione del modulo __main__ . Quel testo afferma:

Questo modulo rappresenta l'ambito (altrimenti anonimo) in cui viene eseguito il programma principale dell'interprete: comandi letti dall'input standard, da un file di script o da un prompt interattivo. È questo ambiente in cui la stanza "script condizionale" idiomatica causa l'esecuzione di uno script:

if __name__ == '__main__':
    main()



Cosa succede if __name__ == "__main__": do?

__name__ è una variabile globale (in Python, in realtà globale indica a livello di modulo ) che esiste in tutti gli spazi dei nomi. Tipicamente è il nome del modulo (come tipo str ).

Come l'unico caso speciale, comunque, in qualunque processo Python tu corra, come in mycode.py:

python mycode.py

Al namespace globale altrimenti anonimo viene assegnato il valore di '__main__' al suo __name__ .

Quindi, comprese le linee finali

if __name__ == '__main__':
    main()
  • alla fine del tuo script mycode.py,
  • quando è il principale, modulo entry-point che viene eseguito da un processo Python,

causerà l'esecuzione della funzione main definita in modo univoco.

Un altro vantaggio dell'uso di questo costrutto: puoi anche importare il tuo codice come modulo in un altro script e quindi eseguire la funzione principale se e quando il tuo programma decide:

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



Quando ci sono determinate affermazioni nel nostro modulo ( M.py ) che vogliamo essere eseguite quando verrà eseguito come principale (non importato), possiamo mettere quelle dichiarazioni (test-case, dichiarazioni di stampa) sotto questo blocco if .

Come per impostazione predefinita (quando il modulo viene eseguito come principale, non importato) la variabile __name__ è impostata su "__main__" , e quando verrà importata la variabile __name__ otterrà un valore diverso, molto probabilmente il nome del modulo ( 'M' ). Ciò è utile nell'esecuzione di diverse varianti di moduli insieme e nella separazione delle loro specifiche istruzioni di input e output e anche in caso di casi di test.

In breve , usa questo blocco " if __name__ == "main" " per impedire che il codice (certo) venga eseguito quando il modulo viene importato.




In __name__ semplici, __name__ è una variabile definita per ogni script che definisce se lo script viene eseguito come modulo principale o se viene eseguito come un modulo importato.

Quindi se abbiamo due script;

#script1.py
print "Script 1's name: {}".format(__name__)

e

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

L'output dell'esecuzione di script1 è

Script 1's name: __main__

E l'output dell'esecuzione di script2 è:

Script1's name is script1
Script 2's name: __main__

Come puoi vedere, __name__ ci dice quale codice è il modulo 'principale'. Questo è fantastico, perché puoi semplicemente scrivere codice e non preoccuparti di problemi strutturali come in C / C ++, dove, se un file non implementa una funzione 'principale', allora non può essere compilato come un eseguibile e se lo fa, non può quindi essere usato come una biblioteca.

Supponiamo che tu scriva uno script Python che fa qualcosa di eccezionale e che implementi un carico di funzioni utili per altri scopi. Se voglio usarli posso semplicemente importare il tuo script e usarli senza eseguire il tuo programma (dato che il tuo codice viene eseguito solo nel if __name__ == "__main__": context). Mentre in C / C ++ dovresti dividere quei pezzi in un modulo separato che poi include il file. Immagina la situazione sotto;

Le frecce sono collegamenti di importazione. Per tre moduli ciascuno che tenta di includere il codice dei moduli precedenti, ci sono sei file (nove, contando i file di implementazione) e cinque collegamenti. Ciò rende difficile includere altro codice in un progetto C a meno che non sia compilato specificamente come una libreria. Ora immaginalo per Python:

Scrivi un modulo e, se qualcuno vuole usare il tuo codice, lo importa e la variabile __name__ può aiutare a separare la parte eseguibile del programma dalla parte della libreria.




Tenere conto:

if __name__ == "__main__":
    main()

Controlla se l'attributo __name__ dello script Python è "__main__" . In altre parole, se il programma stesso viene eseguito, l'attributo sarà __main__ , quindi il programma verrà eseguito (in questo caso la funzione main() ).

Tuttavia, se il tuo script Python viene utilizzato da un modulo, verrà eseguito qualsiasi codice al di fuori if \__name__ == "\__main__" , quindi if \__name__ == "\__main__" viene utilizzato solo per verificare se il programma viene utilizzato come modulo o meno, e quindi decide se eseguire il codice.




Ci sono un certo numero di variabili che il sistema (interprete Python) fornisce per i file sorgente (moduli). Puoi ottenere i loro valori ogni volta che vuoi, quindi concentriamoci sulla variabile / attributo __name__ :

Quando Python carica un file di codice sorgente, esegue tutto il codice trovato in esso. (Si noti che non chiama tutti i metodi e le funzioni definiti nel file, ma li definisce).

Prima che l'interprete esegua il file del codice sorgente, definisce alcune variabili speciali per quel file; __name__ è una di quelle variabili speciali che Python definisce automaticamente per ogni file di codice sorgente.

Se Python sta caricando questo file del codice sorgente come programma principale (cioè il file che si esegue), quindi imposta la variabile __name__ speciale per questo file per avere un valore "__main__" .

Se questo viene importato da un altro modulo, __name__ verrà impostato sul nome di quel modulo.

Quindi, nel tuo esempio in 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 che il blocco di codice:

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

verrà eseguito solo quando si esegue direttamente il modulo; il blocco di codice non verrà eseguito se un altro modulo sta chiamando / importandolo perché il valore di __name__ non sarà uguale a " main " in quella particolare istanza.

Spero che questo aiuti.




È speciale quando viene chiamato un file Python dalla riga di comando. Questo viene in genere utilizzato per chiamare una funzione "main ()" o eseguire un altro codice di avvio appropriato, come ad esempio la gestione degli argomenti della riga di comando.

Potrebbe essere scritto in diversi modi. Un altro è:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

Non sto dicendo che dovresti usare questo nel codice di produzione, ma serve per illustrare che non c'è nulla di "magico" if __name__ == '__main__' . È una buona convenzione per invocare una funzione principale nei file Python.




La ragione per

if __name__ == "__main__":
    main()

è principalmente quello di evitare i problemi di blocco delle importazioni che potrebbero derivare dall'avere codice direttamente importato . Si desidera eseguire main() se il file è stato richiamato direttamente (si tratta del caso __name__ == "__main__" ), ma se il codice è stato importato, l'importatore deve immettere il codice dal modulo principale vero per evitare problemi di blocco dell'importazione.

Un effetto collaterale è che accedi automaticamente a una metodologia che supporta più punti di accesso. È possibile eseguire il programma utilizzando main() come punto di ingresso, ma non è necessario . Mentre setup.py aspetta main() , altri strumenti usano punti di ingresso alternativi. Ad esempio, per eseguire il tuo file come processo gunicorn , devi definire una funzione app() invece di main() . Proprio come con setup.py , gunicorn importa il tuo codice in modo che tu non voglia fare nulla mentre viene importato (a causa del problema del blocco delle importazioni).




Tenere conto:

print __name__

L'output per quanto sopra è __main__ .

if __name == "__main__":
  print "direct method"

L'affermazione sopra è vera e stampa "metodo diretto" . Supponiamo che importando questa classe in un'altra classe non stampi il "metodo diretto" perché, durante l'importazione, imposterà __name__ equal to "firstmodel name" .




Se questo file .py viene importato da altri file .py, il codice sotto "l'istruzione if" non verrà eseguito.

Se questo .py viene eseguito da python this_py.py sotto shell, o doppio clic su Windows. il codice sotto "l'istruzione if" sarà eseguito.

Di solito è scritto per i test.




Tutte le risposte hanno praticamente spiegato la funzionalità. Ma fornirò un esempio del suo utilizzo che potrebbe aiutare a chiarire ulteriormente il concetto.

Supponiamo che tu abbia due file Python, a.py e b.py. Adesso, a.py importa b.py. Eseguiamo il file a.py, dove viene eseguito prima il codice "import b.py". Prima dell'esecuzione del resto del codice a.py, il codice nel file b.py deve essere eseguito completamente.

Nel codice b.py c'è un codice che è esclusivo di quel file b.py e non vogliamo nessun altro file (diverso dal file b.py), che ha importato il file b.py, per eseguirlo.

Ecco cosa controlla questa riga di codice. Se è il file principale (cioè, b.py) che esegue il codice, che in questo caso non è (a.py è il file principale in esecuzione), quindi viene eseguito solo il codice.




se name == ' main ':

Vediamo se __name__ == '__main__':abbastanza spesso.

Controlla se un modulo viene importato o meno.

In altre parole, il codice all'interno del ifblocco verrà eseguito solo quando il codice viene eseguito direttamente. Qui directlysignifica not imported.

Vediamo cosa fa usando un semplice codice che stampa il nome del modulo:

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

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

Se eseguiamo direttamente il codice tramite python test.py, il nome del modulo è __main__:

call test()
test module name=__main__



Related