2014-12-10 1 views
0

비동기 콜백 :이 실행이 기능 어딘가에 던져 경우를 제외하고 잘 작동토네이도 내가 동시에 실행되는 코드의 비동기 부분이 예외

@tornado.web.asynchronous 
def execute(self, func, *args): 
    def callback(future): 
     try: 
      to_return = json.dumps(future.result()) 
      self.write(to_return) 
      self.flush() 
      self.finish() 
     except: 
      error = error = self.get_exception() 
      self.set_status(500) 
      self.finish(json.dumps({"error": error)) 

    EXECUTOR.submit(
     partial(func, *args) 
    ).add_done_callback(
     lambda future: tornado.ioloop.IOLoop.instance().add_callback(
      partial(callback, future))) 


def get_exception(self): 
    exc_type, exc_obj, tb = sys.exc_info() 
    f = tb.tb_frame 
    lineno = tb.tb_lineno 
    filename = f.f_code.co_filename 
    linecache.checkcache(filename) 
    line = linecache.getline(filename, lineno, f.f_globals) 
    return {'error_msg': 'LINE {} "{}"): {}, {}'.format(filename, lineno, line.strip(), exc_obj, exc_obj)} 

는 스택 추적 만 포인트 곳으로 돌아갑니다 그것은 코드에서 실제로 일어난 곳이 아니라 콜백 (즉, 미래가 실행 된 곳)에 던졌습니다.

원래 던져진 곳의 실제 기능에서 예외를 캡처 할 수 있습니까?

답변

1

파이썬 3에서는 그냥 작동해야합니다. 파이썬 2에서는 ThreadPoolExecutor 주위에 더 자세한 내용을 담을 수있는 래퍼를 작성할 수 있다고 생각하지만 운이 좋다.

Python의 예외/추적 모델이 Python 2와 3 사이에서 변경되었습니다. Python 3에서 Exception 객체는 자체 추적 정보를 가지고 있지만 Python 2에서는 추적 객체가 별도의 객체 (일반적으로 sys.exc_info 트리플을 통해 액세스 됨)입니다. concurrent.futures 패키지는 Python 3에서 백 포트되기 때문에 exc_info 트리플이 아닌 예외 자체 만 캡처하므로 추적이 손실됩니다.

토네이도의 미래 클래스 (tornado.concurrent.Future)는 파이썬 2 (set_exc_info() 메소드)에서 추적을 캡처하는 확장 기능을 가지고 있습니다. 나는 당신이 Executor를 대체하기 위해 이것 (테스트되지 않은)을 할 수 있다고 생각한다. :

def submit_with_traceback(executor, func, *args): 
    tornado_future = tornado.concurrent.Future() 
    def wrapper(): 
     try: 
      result = func(*args) 
     except: 
      tornado.future.set_exc_info(sys.exc_info()) 
     tornado_future.set_result(result) 
    # executor.submit() returns a concurrent.futures.Future; ignore it 
    executor.submit(wrapper) 
    return tornado_future 
+0

감사합니다. – jamborta

관련 문제