[Python] Cosa succede se __name__ == "__main__": do?



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__" .

Question

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



Un sacco di cose diverse qui sulla meccanica del codice in questione, il "come", ma per me niente di tutto ciò 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 , xy.py import ab . L'istruzione import esegue immediatamente il modulo durante l'importazione, quindi le operazioni di ab vengono eseguite prima del resto di xy . Una volta terminato con ab , continua con xy .

L'interprete tiene traccia di quali script sono in esecuzione con __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. A ogni altro script chiamato da questo script "__main__" viene assegnato il nome file come __name__ (ad es. __name__ == "ab.py" ). Quindi, la riga 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 che i blocchi funzione - o def - 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'; chiamiamolo "__main__" nella variabile __name__ .
  • Importa e apri il file con __name__ == "ab.py" .
  • Oh, una funzione. Lo ricorderò.
  • Ok, funzione a() ; L'ho appena saputo. Stampa di " Una funzione in un file ab ".
  • Fine del file; torna a "__main__" !
  • Oh, una funzione. Lo ricorderò.
  • Un altro.
  • Funzione x() ; ok, stampa ' attività periferica: potrebbe essere utile in altri progetti '.
  • Che cos'è questo? Un'istruzione if . Bene, la condizione è stata soddisfatta (la variabile __name__ è stata impostata su "__main__" ), quindi "__main__" la funzione main() e "__main__" main function: this is where the action is ".

Le due righe in basso indicano: "Se questo è lo script main o 'casa', eseguire la funzione chiamata main() ". Ecco perché vedrai un def main(): block up top, che contiene il flusso principale delle funzionalità dello script.

Perché implementarlo?

Ricordi cosa ho detto in precedenza 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, mettere la carne del tuo script nella funzione main() lo mette in quarantena in modo efficace, 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 è che main() solito non viene chiamato esternamente. Quindi potresti chiederti un'altra cosa: se non stiamo chiamando main() , perché chiamiamo il copione? È 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 possono essere chiamate da uno script in linea che non è contenuto in una funzione main() . 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 3a parola di una data stringa di testo, creando una matrice numpy da una lista di numeri e squadrandoli, o detragliando una superficie 3D. Le possibilità sono illimitate.)

[Per inciso, questo thread 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.]




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



È possibile rendere il file utilizzabile sia come script sia come modulo importabile .

fibo.py (un modulo chiamato fibo )

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Riferimento: https://docs.python.org/3.5/tutorial/modules.html




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



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.




Quando esegui Python in modo interattivo, alla variabile __name__ locale viene assegnato un valore di __main__ . Allo stesso modo, quando si esegue un modulo Python dalla riga di comando, anziché importarlo in un altro modulo, al suo attributo __name__ viene assegnato un valore di __main__ , anziché il nome effettivo del modulo. In questo modo, i moduli possono esaminare il proprio valore __name__ per determinare da soli il modo in cui vengono utilizzati, sia come supporto per un altro programma o come applicazione principale eseguita dalla riga di comando. Pertanto, il seguente idioma è abbastanza comune nei moduli Python:

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.



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 blocco if verrà eseguito solo quando il codice viene eseguito direttamente. Qui directly significa not imported .

Vediamo cosa fa usando un semplice codice che stampa il nome della modulazione:

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

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

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

call test()
test module name=__main__



if __name__ == "__main__": è fondamentalmente un ambiente di script di livello superiore, specifica all'interprete che ('Ho la priorità più alta per essere eseguita per prima').

'__main__' è il nome dell'ambito in cui viene eseguito il codice di livello superiore. Il __name__ un modulo è uguale a '__main__' quando letto dallo standard input, uno script o da un prompt interattivo.

if __name__ == "__main__":
    # execute only if run as a script
    main()



Prima di spiegare qualcosa su if __name__ == '__main__' è importante capire cosa __name__ è e cosa fa.

Cos'è __name__ ?

__name__ è un DunderAlias ​​- può essere pensato come una variabile globale (accessibile dai moduli) e funziona in modo simile a quello global .

È una stringa (globale come menzionato sopra) come indicato da type(__name__) (che fornisce <class 'str'> ), ed è uno standard integrato per entrambe le versioni di Python 3 e Python 2 .

Dove:

Non può essere utilizzato solo negli script, ma può anche essere trovato sia nell'interprete che nei moduli / pacchetti.

Interprete:

>>> print(__name__)
__main__
>>>

script:

test_file.py :

print(__name__)

Risultante in __main__

Modulo o pacchetto:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

Risultato in somefile

Si noti che quando viene utilizzato in un pacchetto o modulo, __name__ prende il nome del file. Il percorso del modulo reale o del percorso del pacchetto non è dato, ma ha il suo __file__ __file__ , che consente questo.

Dovresti vedere che, dove __name__ , dove è il file principale (o il programma) restituirà sempre __main__ , e se è un modulo / pacchetto, o qualsiasi cosa che sta scappando da qualche altro script Python, restituirà il nome del file da dove ha avuto origine.

Pratica:

Essere una variabile significa che il suo valore può essere sovrascritto ("can" non significa "should"), sovrascrivendo il valore di __name__ si __name__ una mancanza di leggibilità. Quindi non farlo, per nessuna ragione. Se hai bisogno di una variabile, definisci una nuova variabile.

Si assume sempre che il valore di __name__ sia __main__ o il nome del file. Ancora una volta la modifica di questo valore predefinito causerà più confusione sul fatto che farà del bene, causando problemi in futuro.

esempio:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

In generale, è considerata buona pratica includere if __name__ == '__main__' negli script if __name__ == '__main__' .

Ora per rispondere if __name__ == '__main__' :

Ora sappiamo che il comportamento di __name__ cose diventano più chiare:

Un if è un'istruzione di controllo di flusso che contiene il blocco di codice che verrà eseguito se il valore dato è vero. Abbiamo visto che __name__ può utilizzare __main__ o il nome del file da cui è stato importato.

Ciò significa che se __name__ è uguale a __main__ allora il file deve essere il file principale e deve essere effettivamente in esecuzione (o è l'interprete), non un modulo o pacchetto importato nello script.

Se infatti __name__ prende il valore di __main__ allora qualunque cosa si trova in quel blocco di codice verrà eseguita.

Questo ci dice che se il file in esecuzione è il file principale (o stai eseguendo direttamente dall'interprete), allora questa condizione deve essere eseguita. Se è un pacchetto, allora non dovrebbe, e il valore non sarà __main__ .

moduli:

__name__ può essere utilizzato anche nei moduli per definire il nome di un modulo

varianti:

È anche possibile fare altre cose, meno comuni ma utili con __name__ , alcune mostrerò qui:

Eseguendo solo se il file è un modulo o pacchetto:

if __name__ != '__main__':
    # Do some useful things 

Esecuzione di una condizione se il file è il principale e un altro se non lo è:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

Puoi anche usarlo per fornire funzioni / utility di aiuto eseguibili su pacchetti e moduli senza l'uso elaborato di librerie.

Consente inoltre ai moduli di essere eseguiti dalla riga di comando come script principali, che può essere anche molto utile.




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.




Links