L'eccezione è sollevata. Il blocco finally
viene eseguito quando il generatore viene chiuso. La chiusura di un generatore viene effettuata aumentando un GeneratorExit
exception nel contesto del generatore.
L'eccezione in ignorato perché il generatore non è chiuso fino a quando non viene eliminato (automaticamente in questo caso, quando Python termina); il conduttore generatore __del__
chiude il generatore, che attiva il blocco finally:
:
>>> def mycoroutine():
... try:
... while True:
... data = (yield)
... print data
... finally:
... raise ValueError
... print "END"
...
>>> co = mycoroutine()
>>> co.next()
>>> co.close()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in mycoroutine
ValueError
>>> co = mycoroutine()
>>> co.next()
>>> del co
Exception ValueError: ValueError() in <generator object mycoroutine at 0x1046a9fa0> ignored
eccezioni sollevate durante pulitura vengono sempre ignorati; vedere la object.__del__()
documentation:
Attenzione: A causa delle circostanze precarie in cui vengono chiamati i __del__()
metodi, eccezioni che si verificano durante la loro esecuzione sono ignorati, e un avvertimento viene stampato sys.stderr
invece.
La soluzione è quella di non avere eccezioni essere sollevate quando un generatore è ripulito, o intercettare l'eccezione chiudendo il generatore in modo esplicito:
>>> co = mycoroutine()
>>> co.next()
>>> try:
... co.close()
... except ValueError:
... pass
...
>>> del co
>>> # No exception was raised
...
Si potrebbe anche intercettare l'eccezione GeneratorExit
ed eseguire un po di pulizia a quel punto:
def mycoroutine():
try:
while True:
data = (yield)
print data
except GeneratorExit:
print "Generator exiting!"
ma si noti che qualsiasi eccezione diverso sarà sempre essere propagati StopIteration
o GeneratorExit
; vedere la generator.close()
documentation:
Se la funzione di generatore solleva poi StopIteration
(chiudendo normalmente, oa causa di già essendo chiusa) o GeneratorExit
(da non prendere l'eccezione), vicino torna al suo chiamante. Se il generatore produce un valore, viene generato un valore RuntimeError
. Se il generatore genera altre eccezioni, viene propagato al chiamante.
La stessa cosa accade se sostituisco 'finally'" con 'tranne GeneratorExit:' Suppongo che sia lo stesso ... – Zac
@Zac:. Naturalmente lo fa, è ancora * * rilancio di un 'ValueError' , non si? Cattura 'GeneratorExit' e sollevando un'altra eccezione non impedisce l'propagazione dell'eccezione. –