2012-02-13 17 views
6

Zrobiłem Greenlet i połączyłem go z wywoływaczem. Jakiś czas później, Greenlet kończy się niepowodzeniem z wyjątkiem. Połączona wywołanie można wywołać. To wszystko świetnie!jak przechwycić traceback w geenie

Oto problem:

traceback wyjątku na mojej konsoli pojawia się, jak można się spodziewać. Ale chcę robić rzeczy z tym tracebackiem w powiązanej podpowiedzi. Jak uzyskać dostęp do tego tracebacku w ramach połączonego wywołania?

(Mój pierwszy instynkt było użyć traceback.extract_stack(), ale okazuje się, że zapewnia traceback dla połączonego na żądanie siebie, a nie dla wyjątku.)

Odpowiedz

15

Trackback nie jest celowo zapisywany, gdy Greenlet umiera. Jeśli zostałby zapisany, utrzymywałby przy życiu wiele obiektów, które powinny zostać usunięte, co ma szczególne znaczenie, jeśli obiekt zarządza jakimś zasobem (otwartym plikiem lub gniazdem).

Jeśli chcesz zapisać ślad zwrotny, musisz zrobić to sam.

+1

I TO jest autorytatywna odpowiedź. Dzięki, Denis. – kkurian

1

Wystarczy upewnić się chwycić wartość exception z Greenlet i wyrzucić go poza Greenlet np get zyski albo wartość zwróconych lub podnosi interna l wyjątek.

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 

Powinien dać ci to, czego potrzebujesz.

+0

Próbuję uzyskać traceback w powiązanej wywoływalne (np. Foo = gevent.Greenlet (x); foo.link_exception (bar); foo.start(); ; ) - robienie tego, co zasugerowałeś w bar() nie generuje traceback dla Exception, ponieważ zostało podniesione w foo, tworzy traceback dla Exception, ponieważ jest on podnoszony na pasku. – kkurian

+0

Być może powinieneś wkleić swój kod wyżej, twój problem wydaje się być problemem z zakresu i łatwiej byłoby debugować, gdybyśmy mogli zobaczyć, jak konfigurujesz swoje zasięgi. –

0

Jako alternatywa dla rozwiązania Stephena Diehla z użyciem 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

Odrodziłbyś się, a nie link, a nie tworzenie, linkowanie i uruchamianie? Czy jest jakaś praktyczna różnica? – kkurian

+0

Czy rozwiązuje to obawy, które wysunąłem w komentarzach do rozwiązania Diehla? – kkurian

+0

Zakładam, że teoretycznie może się zdarzyć, że greenlet ulegnie awarii, zanim link zostanie utworzony w ten sposób. – renstrm