2012-02-13 17 views
6

He generado un Greenlet y lo he vinculado a un callable. Algún tiempo después, el Greenlet falla con una excepción. Se llama al enlace llamable. ¡Eso es genial!cómo capturar un traceback en gevent

Aquí está el problema:

El rastreo de la excepción aparece en mi consola, como era de esperar. Pero quiero hacer cosas con ese rastreo dentro del enlace invocable. ¿Cómo obtengo acceso a ese rastreo dentro del enlace llamable?

(Mi primer instinto fue utilizar traceback.extract_stack(), pero resulta que proporciona un rastreo para el propio exigible vinculados y no la excepción.)

Respuesta

15

El rastreo no se guarda intencionalmente cuando se agota el Greenlet. Si se guardó, mantendría vivos muchos objetos que se espera que se eliminen, lo cual es especialmente importante si el objeto gestiona algún recurso (archivo o socket abierto).

Si desea guardar el rastreo, tiene que hacerlo usted mismo.

+1

Y ESA es una respuesta autorizada. Gracias, Denis. – kkurian

1

Sólo asegúrese de agarrar el valor de la exception Greenlet y lo lanza fuera del Greenlet, por ejemplo get devuelve o el valor devuelto o aumenta la interna l excepción.

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 

Debería darle lo que necesita.

+0

Estoy tratando de obtener el traceback dentro de un enlace invocable (por ejemplo, foo = gevent.Greenlet (x); foo.link_exception (barra); foo.start(); ; ): hacer lo que has sugerido dentro de bar() no produce el rastreo para la Excepción, ya que se planteó en foo, produce el rastreo para la Excepción cuando se levanta en la barra. – kkurian

+0

Quizás deba pegar el código arriba, su problema parece ser un problema de alcance y sería más fácil de depurar si pudiéramos ver cómo está configurando sus ámbitos. –

0

Como una alternativa a la solución de Stephen Diehl usando 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

¿Engendrarías entonces vincularías en lugar de crear, vincular y comenzar? ¿Hay alguna diferencia práctica? – kkurian

+0

¿Responde esto a las preocupaciones que planteé en los comentarios a la solución de Diehl? – kkurian

+0

Bueno, supongo que teóricamente el greenlet podría bloquearse antes de que el enlace se cree de esta manera. – renstrm

Cuestiones relacionadas