Domanda Cosa succede se __name__ == "__main__": do?


Cosa fa il if __name__ == "__main__": fare?

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

4126
2018-01-07 04:11


origine


risposte:


Quando l'interprete Python legge un file sorgente, esegue tutto il codice trovato in esso.

Prima di eseguire il codice, definirà alcune variabili speciali. Ad esempio, se l'interprete Python esegue quel modulo (il file sorgente) come programma principale, imposta lo speciale __name__ variabile per avere un valore "__main__". Se questo file viene importato da un altro modulo, __name__ sarà impostato sul nome del modulo.

Nel caso del tuo script, supponiamo che sia in esecuzione come funzione principale, ad es. hai detto qualcosa del genere

python threading_example.py

sulla riga di comando. Dopo aver impostato le variabili speciali, eseguirà il file import dichiarazione e caricare quei moduli. Quindi valuterà il def blocco, creando un oggetto funzione e creando una variabile chiamata myfunction che punta all'oggetto funzione. Quindi leggerà il if affermazione e vediamo che __name__ fa uguale "__main__", quindi eseguirà il blocco mostrato lì.

Una ragione per farlo è che a volte scrivi un modulo (a .py file) dove può essere eseguito direttamente. In alternativa, può anche essere importato e utilizzato in un altro modulo. Effettuando il controllo principale, è possibile eseguire quel codice solo quando si desidera eseguire il modulo come programma e non farlo eseguire quando qualcuno vuole solo importare il modulo e chiamare da sé le proprie funzioni.

Vedere questa pagina  per alcuni dettagli aggiuntivi.


4406
2018-01-07 04:26



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 altre lingue, non c'è main() funzione che viene eseguita automaticamente - il main() la funzione è implicitamente tutto il codice al livello superiore.

In questo caso, il codice di livello superiore è un if bloccare. __name__ è una variabile built-in che valuta il nome del modulo corrente. Tuttavia, se un modulo viene eseguito direttamente (come in myscript.py sopra), quindi __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 verrà eseguito il codice di primo livello, ma il codice nel corpo del if la clausola sopra non verrà eseguita poiché la condizione non è soddisfatta. 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 corri two.py anziché:

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, è __name__ equivale "one" invece di "__main__".


1400
2018-01-07 04:28



La spiegazione più semplice per __name__ variabile (imho) è la seguente:

Crea i seguenti file.

# a.py
import b

e

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

Eseguendoli otterrai questo risultato:

$ python a.py
Hello World from b!

Come puoi vedere, quando un modulo viene importato, set Python globals()['__name__'] in questo modulo al nome del modulo.

$ python b.py
Hello World from __main__!
Hello World again from __main__!

Come puoi vedere, quando viene eseguito un file, Python imposta globals()['__name__'] in questo file per "__main__".


560
2018-01-07 11:35



Cosa fa il if __name__ == "__main__": fare?

Per delineare le basi:

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

  • Quindi, codice sotto il if il blocco 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"""

tu poteva  prova 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

All'importazione, il do_important sarebbe chiamata la funzione, quindi probabilmente commenteresti la tua chiamata di funzione, do_important(), in fondo.

# 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

Il __name__ punti variabili 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, ovvero l'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 mentre sviluppiamo e testiamo in una funzione come questa, facciamo il nostro controllo '__main__' subito dopo:

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 il main funzione, e consentirà anche al modulo (e alle sue funzioni e classi) di essere chiamato quando si esegue da un altro '__main__' modulo, cioè

import important
important.main()

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

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

if __name__ == '__main__':
    main()

412
2017-11-23 04:38



if __name__ == "__main__"è la parte che viene eseguita quando lo script viene eseguito da (ad esempio) la riga di comando utilizzando un comando simile python myscript.py.


92
2018-01-07 04:14



Cosa fa if __name__ == "__main__": fare?

__name__ è una variabile globale (in Python, global significa in realtà sul livello del modulo ) che esiste in tutti gli spazi dei nomi. In genere è il nome del modulo (come a str genere).

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, incluso 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,

farà sì che lo script sia definito in modo univoco main funzione da eseguire.

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

57
2017-10-14 20:22



Ci sono molte prese diverse qui sulla meccanica del codice in questione, il "come", ma per me nessuna di queste aveva senso finché non ho capito il "perché". Questo dovrebbe essere particolarmente utile per i nuovi programmatori.

Prendi il file "ab.py":

def a():
    print('A function in ab file');
a()

E un secondo file "xy.py":

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

Cosa sta facendo in realtà questo codice?

Quando esegui xy.py, tu import ab. L'istruzione import esegue immediatamente il modulo durante l'importazione, quindi abLe operazioni vengono eseguite prima del resto di xy'S. Una volta finito con ab, continua con xy.

L'interprete tiene traccia di quali script sono in esecuzione __name__. Quando esegui uno script, indipendentemente da come lo hai chiamato, l'interprete lo chiama "__main__", rendendolo lo script master o 'home' a cui viene restituito dopo aver eseguito uno script esterno.

Qualsiasi altro script chiamato da questo "__main__" lo script ha il suo nome come suo __name__ (per esempio., __name__ == "ab.py"). Quindi, la linea if __name__ == "__main__": è il test dell'interprete per determinare se sta interpretando / analizzando lo script 'home' che è stato inizialmente eseguito, o se sta sbirciando temporaneamente in un altro script (esterno). Ciò consente al programmatore di avere lo script in modo che si comporti diversamente se viene eseguito direttamente o chiamato esternamente.

Passiamo attraverso il codice di cui sopra per capire cosa sta succedendo, concentrandoci prima sulle linee non indirizzate e sull'ordine in cui appaiono negli script. Ricorda quella funzione - o def - I blocchi non fanno nulla da soli fino a quando non vengono chiamati. Cosa potrebbe dire l'interprete se biascicato a se stesso:

  • Apri xy.py come file 'casa'; chiamalo "__main__" nel __name__ variabile.
  • Importa e apri il file con __name__ == "ab.py".
  • Oh, una funzione. Lo ricorderò.
  • Ok, funzione a(); L'ho appena saputo. Stampa Una funzione in un file ab '.
  • Fine del file; di nuovo a "__main__"!
  • Oh, una funzione. Lo ricorderò.
  • Un altro.
  • Funzione x(); ok, stampa ' compito periferico: potrebbe essere utile in altri progetti '.
  • Che cos'è questo? Un if dichiarazione. Bene, la condizione è stata soddisfatta (la variabile __name__è stato impostato su "__main__"), quindi inserirò il main() funzione e stampa ' funzione principale: questo è dove si trova l'azione '.

Le due righe in basso indicano: "Se questo è il "__main__" o 'home' script, eseguire la funzione chiamata main()"Ecco perché vedrai a def main(): bloccare in alto, che contiene il flusso principale delle funzionalità dello script.

Perché implementarlo?

Ricordi cosa ho detto prima sulle dichiarazioni di importazione? Quando si importa un modulo, non lo "riconosce" solo e attende ulteriori istruzioni - in realtà esegue tutte le operazioni eseguibili contenute nello script. Quindi, mettendo la carne del tuo script nel main() funziona efficacemente in quarantena, mettendolo in isolamento in modo che non venga immediatamente eseguito quando importato da un altro script.

Di nuovo, ci saranno delle eccezioni, ma la pratica comune è quella main() di solito non viene chiamato esternamente. Quindi potresti chiederti un'altra cosa: se non stiamo chiamando main()perché stiamo chiamando la sceneggiatura? È perché molte persone strutturano i propri script con funzioni autonome costruite per essere eseguite indipendentemente dal resto del codice nel file. Successivamente verranno chiamati da qualche altra parte nel corpo della sceneggiatura. Il che mi porta a questo:

Ma il codice funziona senza di esso

Sì, è giusto. Queste funzioni separate può  essere chiamato da uno script in-line che non è contenuto in a main() funzione. Se sei abituato (come lo sono io, nelle prime fasi di apprendimento della programmazione) a creare script in-line che fanno esattamente ciò che ti serve, e proverai a capirlo di nuovo se hai ancora bisogno di quell'operazione di nuovo. beh, non sei abituato a questo tipo di struttura interna del tuo codice, perché è più complicato da compilare e non è così intuitivo da leggere.

Ma quello è uno script che probabilmente non può avere le sue funzioni chiamate esternamente, perché se lo facesse inizierebbe immediatamente a calcolare e assegnare variabili. Ed è probabile che se stai cercando di riutilizzare una funzione, il tuo nuovo script è strettamente correlato a quello vecchio che ci saranno variabili in conflitto.

Nel dividere le funzioni indipendenti, ottieni la possibilità di riutilizzare il tuo lavoro precedente chiamandoli in un altro script. Ad esempio, "example.py" potrebbe importare "xy.py" e chiamare x(), facendo uso della funzione 'x' da "xy.py". (Forse sta capitalizzando la terza parola di una determinata stringa di testo, creando una matrice NumPy da un elenco di numeri e squadrandoli, o detrando una superficie 3D. Le possibilità sono illimitate.)

(A parte, questa domanda  contiene una risposta di @kindall che finalmente mi ha aiutato a capire - il perché, non il come. Sfortunatamente è stato contrassegnato come un duplicato di questo , che penso sia un errore).


47
2017-09-29 04:33