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




14 Answers

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 la variabile __name__ speciale per avere un valore "__main__" . Se questo file viene importato da un altro modulo, __name__ verrà impostato sul nome del modulo.

Nel caso del tuo script, supponiamo che si stia eseguendo come funzione principale, ad esempio hai detto qualcosa del genere

python threading_example.py

sulla riga di comando. Dopo aver impostato le variabili speciali, eseguirà l'istruzione import e caricherà quei moduli. Quindi valuterà il blocco def , creando un oggetto funzione e creando una variabile chiamata myfunction che punta all'oggetto function. Quindi leggerà l'istruzione if e vedrà che __name__ equivale a "__main__" , quindi eseguirà il blocco mostrato lì.

Una ragione per farlo è che a volte si scrive un modulo (un file .py ) 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.

Vedi questa pagina per ulteriori dettagli.

Nota (di Stainsor): se inserisci il codice prima delle definizioni di funzione, verrà eseguito prima di main.

print("This code executes before main.") 

def functionA():
    print("Function A")

def functionB():
    print("Function B")

if __name__ == '__main__':
    functionA()
    functionB()

Se questo modulo è effettivamente principale, questo codice risulta in:

This code executes before main. 
Function A 
Function B

Se questo modulo non è main, ottieni:

This code executes before main. 
to define

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



La spiegazione più semplice per la variabile __name__ (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, Python imposta 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 su "__main__" .




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




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 , 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 "__main__" o" home ", eseguire la funzione denominata 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 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, 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 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.)

(Per inciso, 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 credo sia un errore.)




Diamo un'occhiata alla risposta in un modo più astratto:

Supponiamo di avere questo codice in x.py:

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

I blocchi A e B vengono eseguiti quando si esegue "x.py".

Ma il blocco A (e non B) viene eseguito quando eseguiamo un altro modulo, "y.py" per esempio, in cui xy è importato e il codice viene eseguito da lì (come quando una funzione in "x.py" è chiamato da y.py).




Quando esegui Python in modo interattivo, alla variabile __name__ locale viene assegnato un valore __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.



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 effettivo 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.




Penso che sia meglio rompere la risposta in profondità e con parole semplici:

__name__ : ogni modulo in Python ha uno speciale attributo chiamato __name__ . È una variabile built-in che restituisce il nome del modulo.

__main__ : Come altri linguaggi di programmazione, anche Python ha un punto di ingresso per l'esecuzione, cioè main. '__main__' è il nome dell'ambito in cui viene eseguito il codice di livello superiore . Fondamentalmente hai due modi per usare un modulo Python: eseguilo direttamente come script o importalo. Quando un modulo viene eseguito come script, il suo __name__ è impostato su __main__ .

Pertanto, il valore dell'attributo __name__ è impostato su __main__ quando il modulo viene eseguito come programma principale. Altrimenti il ​​valore di __name__ è impostato per contenere il nome del modulo.




if __name__ == "__main__": è fondamentalmente l'ambiente di script di livello superiore e 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()



È 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




Ho letto molto durante le risposte su questa pagina. Direi che se conosci la cosa, sicuramente capirai quelle risposte, altrimenti, sei ancora confuso.

Per essere brevi, è necessario conoscere diversi punti:

  1. import a un'azione in realtà esegue tutto ciò che può essere eseguito in "a"

  2. A causa del punto 1, potresti non voler che tutto venga eseguito in "a" durante l'importazione

  3. Per risolvere il problema al punto 2, python consente di inserire un controllo di condizione

  4. __name__ è una variabile implicita in tutti i moduli .py; quando a.py viene importato, il valore di __name__ del modulo a.py è impostato sul suo nome file "a"; quando a.py viene eseguito direttamente usando "python a.py", che significa a.py è il punto di ingresso, allora il valore di __name__ del modulo a.py è impostato su una stringa __main__

  5. Sulla base del meccanismo su come python imposta la variabile __name__ per ogni modulo, sai come raggiungere il punto 3? La risposta è abbastanza facile, giusto? Metti una condizione if: if __name__ == "__main__": ... ; puoi anche mettere if __name__ == "a" seconda delle tue necessità funzionali

La cosa importante a cui Python è speciale è il punto 4! Il resto è solo una logica di base.




Crea un file, a.py :

print(__name__) # It will print out __main__

__name__è sempre uguale a __main__ogni volta che il file viene eseguito direttamente mostrando che questo è il file principale.

Crea un altro file, b.py , nella stessa directory:

import a  # Prints a

Eseguirlo. Stampa un , cioè il nome del file che viene importato .

Quindi, per mostrare due diversi comportamenti dello stesso file , questo è un trucco comunemente usato:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly



Questa risposta è per i programmatori Java che stanno imparando Python. Ogni file Java contiene in genere una classe pubblica. Puoi usare quella classe in due modi:

  1. Chiama la classe da altri file. Devi solo importarlo nel programma chiamante.

  2. Esegui la classe stand alone, a scopo di test.

Per quest'ultimo caso, la classe deve contenere un metodo public static void main (). In Python questo scopo è servito dall'etichetta globalmente definita '__main__'.




Recentemente, mi sono imbattuto in questo mentre creavo una classe in python (deep learning) e per la mia comprensione e in accordo con le spiegazioni sopra elencate, elaborerò

__name__=="__main__"

Come a volte costruiamo una classe in un file .py e definiamo molte funzioni all'interno di quella classe. ma non vogliamo elaborare tutte quelle funzioni di classe per un unico scopo. per esempio, per creare una classe e definire alcune funzioni per la creazione dei dati (file .npy) mentre altre per il caricamento dei dati. quindi se definiamo

__name__=="__main__"

xxx = nome_classe ()

xxx.create_data ()

Significa se chiamiamo il file .py, quindi creerà solo i dati e non elaborerà altre funzioni di classe. altre funzioni di classe (caricamento dei dati) possono anche essere importate da altre classi.




Related