2013-05-28 2 views
2

말하자면, gen.engine으로 래핑 된 함수가있어 콜백 체인을 "곧바로"즉 코드가 동기식으로 보이게합니다./linear/뭐든간에.다른 함수로 tornado.gen.engine-wrapped 함수를 래핑하기

기능은, 다음 등이

@gen.engine 
def func(): 
    ... 
    yield gen.Task(...) 
    ... 
    yield gen.Task(...) 

과 같습니다. 나는 분명히 gen.Task에 의해 싸여있는 함수에서 발생하는 예외를 잡기 위해 yield 주위에 try/except를 사용할 수 있음을 이해합니다. 함수 func을 다른 함수로 랩핑해야한다면 (실제로 사용 사례입니다) func에있는 "잡히지 않는"예외를 잡아 내지 않으면 안됩니다. func?

나는이 함께 왔어요 :

@gen.engine 
def func(..., callback): 
    ... 
    callback() 

@gen.engine 
def outer(): 
    try: 
     yield gen.Task(func) 
    except Exception as e: 
     # Log the exception 
    # Stop ioloop (or something) 

이것은 func 일반성의 비트를 추가하지만 추가 인수 및 func에서 일부 인공 논리를 소개합니다.

다른 방법이 있습니까? "긴급 예외가 잡히는"것은이 질문의 목적을위한 인공적인 사용 사례 (이것은 다른 방법으로 가능할 수 있음)입니다. 내가 뭘 찾고있는 것은 tornado.gen을 호출하는 올바른 방법입니다. 다른 기능에서 엔진 랩 기능.

편집 : 어리석은 저, 나는 토네이도 2.x에 제한되었다고 언급 했어야했습니다!

답변

6

@gen.coroutinehttp://www.tornadoweb.org/en/stable/releases/v3.0.0.html에서 토네이도 3의 새로운 기능 :

새로운 데코레이터 @의 gen.coroutine는 gen.engine @ 에 대한 대안으로 사용할 수 있습니다. 자동으로 Future를 반환하고, 콜백을 호출하는 대신 함수 내에서 raise gen.Return (value) (또는 단순히 파이썬 3.3에서 반환 값)으로 값을 반환합니다.

는 문서 (http://www.tornadoweb.org/en/stable/gen.html#tornado.gen.coroutine)에서이 데코레이터

기능은 미래를 반환합니다. 또한 콜백 키워드 인수를 사용하여 호출 할 수도 있습니다.이 인수는 해결 될 때 미래의 결과와 함께 호출됩니다. coroutine이 실패하면 콜백은 실행되지 않고 주변 StackContext로 예외가 발생합니다. 콜백 인수는 데코 레이팅 된 함수 내에서 볼 수 없습니다. 그것은 데코레이터 자체에 의해 처리된다.

따라서 콜백에 대해 걱정할 필요가 없으며 기능을 tornado.gen.Task()으로 줄 필요가 없습니다. 체인은 이제 쉽게 :

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import logging 

import tornado.httpserver 
import tornado.ioloop 
import tornado.options 
import tornado.web 
import tornado.gen 

from tornado.options import define, options 
define("port", default=8000, help="run on the given port", type=int) 

class MainHandler(tornado.web.RequestHandler): 
    @tornado.gen.coroutine 
    def outer(self): 
     logging.info('outer starts') 
     yield self.inner() 
     yield self.inner() 
     logging.info('outer ends') 
     raise tornado.gen.Return('hello') 

    @tornado.gen.coroutine 
    def inner(self): 
     logging.info('inner runs') 

    @tornado.web.asynchronous 
    @tornado.gen.coroutine 
    def get(self): 
     res = yield self.outer() 
     self.write(res) 

if __name__ == "__main__": 
    tornado.options.parse_command_line() 
    app = tornado.web.Application(handlers=[(r"/", MainHandler)]) 
    http_server = tornado.httpserver.HTTPServer(app) 
    http_server.listen(options.port) 
    tornado.ioloop.IOLoop.instance().start() 

출력 : 파이썬 3.3에서

$ python test.py 
[I 130529 03:18:35 test:21] outer starts 
[I 130529 03:18:35 test:29] inner runs 
[I 130529 03:18:35 test:29] inner runs 
[I 130529 03:18:35 test:24] outer ends 
[I 130529 03:18:35 web:1514] 200 GET/(127.0.0.1) 1.48ms 

gen.Result()를 사용할 필요가없고, 간단한 return 할 것입니다. 이전 버전에서는 'return' with argument inside generator 오류가 발생합니다.또한

, 검사 : https://github.com/facebook/tornado/issues/759

업데이트 :

가 토네이도 2.X에 관해서는 내가 콜백을 숨길 수있는 간단한 방법이 없다 생각합니다. 문서 상태 :

대부분의 경우 엔진으로 장식 된 함수는 콜백 인수를 취해 끝나면 결과와 함께 호출해야합니다. 하나는 이고, 예외 콜백 인수 대신 이 self.finish()를 사용하는 RequestHandler get/post/etc 메소드가 예외입니다.

그래서 나는 그 피할 수없는 것이 두려워요. 예 :

class MainHandler(tornado.web.RequestHandler): 
    @tornado.web.asynchronous 
    @tornado.gen.engine 
    def get(self): 
     res = yield tornado.gen.Task(self.outer) 
     self.write(res) 
     self.finish() 

    def inner(self, callback): 
     logging.info('inner runs') 
     callback() 

    @tornado.gen.engine 
    def outer(self, callback): 
     logging.info('outer starts') 
     yield tornado.gen.Task(self.inner) 
     yield tornado.gen.Task(self.inner) 
     logging.info('outer ends') 
     callback("hello") 
+0

weeeell, 네, 답해 주셔서 감사합니다.하지만 불행히도 저는 토네이도 2.x로 제한된다는 것을 잊었습니다. 그렇지 않으면, 나는 기쁘다, 토네이도에서 더 적은 농구를 뛰어 넘어야한다. 3. 그럼에도 불구하고 당신의 노력에 감사한다. – shylent

+0

@shylent. 나는 나의 대답을 업데이트했다. – Nykakin

+0

바로 감사합니다. 기본적으로, 나는 내 질문에 제시 한 접근법 만이 유일한 것이고, 이는 알아두면 좋다는 것을 확인시켜 준다. – shylent

관련 문제