tornado chat demo program
tornado chat demo program(ref. 1) 에 대한 sequence diagram 이다.Future
tornado 의 Future 는 tornado.concurrent.Future 을 사용하는데, concurrent.futures.Future 와 비슷하다. 그런데 tornado.concurrent.Future 는 thread-safe 하지 않다. 그래서 single-threaded event loop 에서 사용할 때는 훨씬 빠르다.[ref. 2]asynchronous 결과 를 전달 할 때 쓰는 object (placeholder) 이다. 흔히 asynchronous operation 의 result 를 Future 가 encapsulate 했다고 표현한다.
synchronous application 에서는 이 Future 를 이용해서 thread 의 result 를 받을 때까지 기다리는 용도로 사용된다.
Tornado 에서는 이 녀석을 다음 2가지 방법으로 사용할 수 있다.
- IOLoop.add_future
- @gen.coroutine 에서 yield 를 사용하는 방법
Tornado 에서 Future 를 사용하는게 좋다고 한다. 2가지 이점이 있는데,
- Error handling : Future.result method 가 간단하게 exception 을 발생시킬 수 있어서 에러 처리가 좀 더 일관되고
- Future 들은 coroutine 들을 사용해서 그들을 잘 빌려준다.(lend)
from tornado.concurrent import Future def async_fetch_future(url): http_client = AsyncHTTPClient() my_future = Future() fetch_future = http_client.fetch(url) fetch_future.add_done_callback( lambda f: my_future.set_result(f.result())) return my_future
위의 코드가 Tornado 에서 @gen.coroutine 이라는 decorator 를 이용해서 아래와 같이 변경된다.
from tornado import gen @gen.coroutine def fetch_coroutine(url): http_client = AsyncHTTPClient() response = yield http_client.fetch(url) raise gen.Return(response.body) # python 2 에서 사용할 때는 raise 를 사용한다.
return 대신에 python 2 에서 raise 를 이용하는 이유는 python2 에서는 generator (yield 를 포함하는 함수)가 값을 return 할 수 없기 때문이다. 그래서 이것을 극복하려고 Return 이라는 Exception 을 raise 하고 있다.
coroutine 은 이 exception 을 잡아서 return value 를 처리한다. python 3.3 이상에서는 그냥 return 을 사용해서 값을 넘길 수 있어서 그냥 return response.body 를 하면 된다.await, async
python 3.5 에서 async 와 await 을 제공하는데, 위에서 사용하는 yield 대신에 await 을 사용하고, def 에 async 를 사용하는 것이 훨씬 빠르다고 한다.[참고]from tornado import gen @gen.coroutine async def fetch_coroutine(url): http_client = AsyncHTTPClient() response = await http_client.fetch(url) return response.body
See Also
References
- tornado/demos/chat at master · tornadoweb/tornado
- tornado.concurrent — Work with threads and futures — Tornado 4.4 documentation
댓글 없음:
댓글 쓰기