2014-11-20 9 views
11

토네이도 코 루틴을 배우려고하는데 아래 코드를 사용하는 중에 오류가 있습니다.토네이도 코 루틴

Traceback (most recent call last): 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\web.py", line 1334, in _execute 
    result = yield result 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 628, in run 
    value = future.result() 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\concurrent.py", line 109, in result 
    raise_exc_info(self._exc_info) 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 631, in run 
    yielded = self.gen.throw(*sys.exc_info()) 
    File "index.py", line 20, in get 
    x = yield 'test' 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 628, in run 
    value = future.result() 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\concurrent.py", line 111, in result 
    raise self._exception 
BadYieldError: yielded unknown object 'test' 

코드 :

from tornado.ioloop import IOLoop 
from tornado.web import RequestHandler, Application, url 
from tornado import gen 

class HelloHandler(RequestHandler): 
    @gen.coroutine 
    def get(self): 
     x = yield 'test' 
     self.render('hello.html') 


def make_app(): 
    return Application(
     [url(r"/", HelloHandler)], 
     debug = True 
    ) 

def main(): 
    app = make_app() 
    app.listen(8888) 
    IOLoop.instance().start() 

main() 
+0

'x = yield'test'' 줄에서 무엇을하려고합니까? –

+0

그 예입니다. 함수의 결과도 얻으려고했습니다. 결과는 같습니다.이 행은 단지 coroutines를 테스트하는 것입니다. – klis87

답변

26

Lutz Horn이 지적한 것처럼 tornado.coroutine 데코레이터는 Future 개의 객체 또는 Future 개의 객체가 포함 된 특정 컨테이너 만 생성해야합니다. 따라서 str을 얻으려고하면 오류가 발생합니다. 내가 놓친 부분은 yield something(), something을 호출하려는 coroutine 내부의 어떤 부분도 coroutine이거나 Future을 반환해야한다는 것입니다. 예를 들어, 다음과 같이 귀하의 예제를 해결할 수 : 심지어이

from tornado.gen import Return 

class HelloHandler(RequestHandler): 
    @gen.coroutine 
    def get(self): 
     x = yield self.do_test() 
     self.render('hello.html') 

    @gen.coroutine 
    def do_test(self): 
     raise Return('test') 
     # return 'test' # Python 3.3+ 

또는을 (일반적으로 당신이 이런 식으로하지 말아야하지만) :

물론
class HelloHandler(RequestHandler): 
    @gen.coroutine 
    def get(self): 
     x = yield self.do_test() 
     self.render('hello.html') 

    def do_test(self): 
     fut = Future() 
     fut.set_result("test") 
     return fut 

는, 이러한 인위적인 예; 실제로는 do_test에서 비동기식 작업을 수행하지 않으므로이를 코 루틴으로 만들 필요가 없습니다. 일반적으로 비동기 입출력을 수행 할 수 있습니다. 예 :

class HelloHandler(RequestHandler): 
    @gen.coroutine 
    def get(self): 
     x = yield self.do_test() 
     self.render('hello.html') 

    @gen.coroutine 
    def do_test(self): 
     http_client = AsyncHTTPClient() 
     out = yield http_client.fetch("someurl.com") # fetch is a coroutine 
     raise Return(out.body) 
     # return out.body # Python 3.3+ 
+0

대단히 감사합니다. do_test 함수의 시작 부분에 time.sleep을 추가했습니다. 모든 것이 작동합니다. 동기 코드에서 sleep (x)가 끝난 후 self.render가 실행됩니다.이 함수가 백그라운드에서 수행되었다고 생각합니다. 그렇지만 실제로는 아닙니다 ... coroutines를 사용하면 어떤 이점이 있습니까? 어쩌면 다른 사용자가 이전 사용자의 잠자기가 끝나기 전에 같은 시간에 연결을 열 수 있습니까? – klis87

+2

@ user3575996'yield function()'을 사용하면'function()'이 완료 될 때까지 coroutine의 실행을 기다리게된다. 그러나 토네이도 I/O 루프를 차단하지 않으므로 클라이언트의 다른 요청이 들어 오면 그 동안 처리 할 수 ​​있습니다. 그러나 블로킹 함수이기 때문에'time.sleep()'를 사용해 테스트 할 수는 없습니다. 비 차단 버전의 절전 모드를 사용해야합니다. 예제는 [이 답변] (http://stackoverflow.com/a/23876402/2073595)을 참조하십시오. – dano

+0

덕분에 이제는 모든 것을 알게되었습니다. – klis87

3

From the documentation : 토네이도에

대부분의 비동기 기능을 돌려 Future; 이 객체를 생성하면 결과가 반환됩니다.

yield a list or dict of Futures 또한 동시에 시작되고 병렬로 실행될 수 있습니다. 그들은 모두 완료되면 목록 또는 결과의 DICT가 반환됩니다

문자열 "test"Future 없습니다. 하나를 양보 해보십시오.

+2

get_all_users() 함수가 데이터베이스 쿼리의 결과를 반환한다고 가정 해 봅시다. 나, 토네이도 예제로 AsyncHTTPClient() 같은 구현 클래스를 사용하는 예제를 줄 수 있겠습니까? – klis87

관련 문제