2014-08-28 28 views
6

avere il codice seguente:eccezione viene eseguito due volte e viene catturato da un diverso blocco except

file1.py

from file2 import tfun 

class TestException(Exception): 
    pass 

try: 
    print 'I am running' 
    tfun() 
except TestException as e: 
    print 'I am caught' 
    print type(e) 
except Exception as e: 
    print 'I am generally caught' 
    print type(e) 

file2.py

def tfun(): 
    from file1 import TestException 
    raise TestException() 

e l'output da python file1.py è il seguente:

I am running 
I am running 
I am caught 
<class 'file1.TestException'> 
I am generally caught 
<class 'file1.TestException'> 

Prima di tutto perché il codice viene eseguito due volte in questo caso? Posso capire che l'importazione è ricorsiva, ma perché il codice dello script viene eseguito nuovamente?

In secondo luogo, la seconda volta che non viene catturato dallo stesso blocco except anche se è lo stesso tipo della prima volta, che anche io non riesco a trovare una spiegazione per.

Infine, sto cercando di trovare una soluzione per questo problema senza spostare nulla in un nuovo file, ma io non sembra essere nessuno. È possibile superare questo problema?

Modifica

Per la seconda domanda ho capito che è perché il codice si trova all'interno del livello di modulo.

+3

+1 per un programma breve, completo, indipendente che dimostra il problema in questione. Rif: http://stackoverflow.com/help/mcve e http://SSCCE.org –

risposta

7

Se si esegue un modulo come uno script (vale a dire dare il suo nome al interprete, invece di importarlo), è caricato con il nome del modulo __main__.

Se si importa lo stesso modulo dal programma, viene ricaricato e rieseguito con il suo nome reale. Se non stai attento, potresti finire a fare cose due volte.

http://effbot.org/zone/import-confusion.htm

Stai caricando file1.py due volte, come due moduli distinti. La prima volta che viene caricata come reesult della linea di comando:

python file1.py 

In tal caso, file1.py viene caricato come modulo principale, __main__.

La seconda volta che si sta caricando come un risultato della sua dichiarazione di importazione:

from file1 import TestException 

In tal caso, file1.py viene caricato come modulo file1.

Poiché file1.py viene caricato come due moduli distinti, ci sono due copie distinte di tutto ciò che contiene. In particolare __main__.TestException è diverso da file1.TestException.

Così, all'interno __main__, la linea:

except TestException as e: 

sta recuperando __main__.TestException anche come tfun() sta sollevando __file1__.TestException. Dentro lo file1, la stessa linea sta recuperando file1.TestException.

Nel primo caso, i tipi non corrispondono e la clausola except: non viene eseguita; in quest'ultimo caso il tipo corrisponde e viene eseguita la clausola except:.

Forse questo programma può renderlo più chiaro che cosa sta accadendo:

from file2 import tfun 

class TestException(Exception): 
    pass 

try: 
    print 'I am calling file2.tfun from', __name__ 
    tfun() 
    print 'I have called file2.tfun from', __name__ 
except TestException as e: 
    print 'I am caught in %s'%(__name__) 
    print type(e), TestException 
except Exception as e: 
    print 'I am generally caught in %s'%__name__ 
    print type(e), TestException 
print 'I am exiting from',__name__ 

Risultato:

$ python file1.py 
I am calling file2.tfun from __main__ 
I am calling file2.tfun from file1 
I am caught in file1 
<class 'file1.TestException'> <class 'file1.TestException'> 
I am exiting from file1 
I am generally caught in __main__ 
<class 'file1.TestException'> <class '__main__.TestException'> 
I am exiting from __main__ 

Una soluzione semplice consiste nel modificare file2.py:

def tfun(): 
    from __main__ import TestException 
    raise TestException() 

Risultato :

$ python file1.py 
I am calling file2.tfun from __main__ 
I am caught in __main__ 
<class '__main__.TestException'> <class '__main__.TestException'> 
I am exiting from __main__ 
+2

+1 La distinzione tra '__main __. TestException' e' file1.TestException' è la parte più difficile, penso. – chepner

Problemi correlati