2012-02-13 18 views
6

Ho generato un Greenlet e l'ho collegato a un callable. Qualche tempo dopo, Greenlet fallisce con un'eccezione. Viene chiamato il callable collegato. È tutto fantastico!come acquisire un traceback in gevent

Ecco il problema:

Il traceback per l'eccezione appare sulla mia console, come ci si aspetterebbe. Ma voglio fare le cose con quel traceback all'interno del callable collegato. Come posso accedere a quel traceback all'interno del callable collegato?

(Il mio primo istinto è stato quello di utilizzare traceback.extract_stack(), ma si scopre che fornisce un traceback per la stessa callable collegato e non per l'eccezione.)

risposta

15

Il traceback non viene salvato intenzionalmente quando il Greenlet muore. Se è stato salvato, manterrebbe molti oggetti vivi che dovrebbero essere eliminati, il che è particolarmente importante se l'oggetto gestisce alcune risorse (file aperto o socket).

Se si desidera salvare il traceback, è necessario farlo da soli.

+1

E QUESTA è una risposta autorevole. Grazie, Denis. – kkurian

1

Basta fare in modo di afferrare il valore exception del Greenlet e gettare fuori del Greenlet, ad esempio get rendimenti sia il valore restituito o solleva l'interna l eccezione.

import traceback 
import gevent 

def fail(): 
    return 0/0 

gl = gevent.spawn(fail) 

try: 
    gl.get() 
except Exception as e: 
    stack_trace = traceback.format_exc() # here's your stacktrace 

Dovrebbe darti quello che ti serve.

+0

Sto cercando di ottenere il traceback all'interno di un oggetto callable collegato (ad esempio, foo = gevent.Greenlet (x); foo.link_exception (bar); foo.start(); ; - facendo ciò che hai suggerito all'interno di bar() non produce il traceback per l'Exception dato che è stato generato in foo, produce il traceback per l'Exception quando viene alzato nella barra. – kkurian

+0

Forse dovresti incollare il tuo codice sopra, il tuo problema sembra un problema di scoping e sarebbe più facile eseguire il debug se potessimo vedere come stai impostando i tuoi ambiti. –

0

In alternativa alla soluzione di Stephen Diehl utilizzando Greenlet.link_exception.

import traceback 

import gevent 

def job(): 
    raise Exception('ooops') 

def on_exception(greenlet): 
    try: 
     greenlet.get() 
    except Exception: 
     err = traceback.format_exc() 
     # Do something with `err` 

g = gevent.spawn(job) 
g.link_exception(on_exception) 
+0

Si genererebbe quindi il collegamento anziché creare, collegare e avviare? C'è qualche differenza pratica? – kkurian

+0

E questo risponde alle preoccupazioni che ho sollevato nei commenti alla soluzione di Diehl? – kkurian

+0

Beh immagino che teoricamente il greenlet potrebbe bloccarsi prima che il collegamento venga creato in questo modo. – renstrm