标签:
在tornad官方文档的Docs》User’s guide》Asynchronous and non-Blocking I/O部分,文中提供了几段示例代码:
a、同步请求代码
from tornado.httpclient import HTTPClient def synchronous_fetch(url): http_client = HTTPClient() response = http_client.fetch(url) return response.body
b、带回调函数的异步请求代码
from tornado.httpclient import AsyncHTTPClient def asynchronous_fetch(url, callback): http_client = AsyncHTTPClient() def handle_response(response): callback(response.body) http_client.fetch(url, callback=handle_response)
c、使用一个 Future 对象替换掉回掉函数
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
d、使用@gen.coroutine装饰的异步请求方式
from tornado import gen@gen.coroutinedef fetch_coroutine(url): http_client = AsyncHTTPClient() response = yield http_client.fetch(url) raise gen.Return(response.body)
下面对这4段代码进行测试:
首先准备数据服务:
URL:’http://localhost:8080/rest/menu‘
METHOD:‘GET‘
返回数据类型:JSON
a.同步请求方法直接调用方法请求,即可得到数据
from tornado.httpclient import HTTPClient def synchronous_fetch(url): """ 简单HttpClient的同步请求 :param url: :return: """ http_client = HTTPClient() response = http_client.fetch(url) return response.body def parse_body(body): """ 解析请求返回值,异步回调函数 :param body: :return: """ print("函数被回调") for line in json.loads(body.decode(encoding=‘utf8‘)): print(line) if __name__ == ‘__main__‘: url = "http://localhost:8080/rest/menu" # 同步请求调用方式 body = synchronous_fetch(url) parse_body(body)
b、异步回调请求,需要将回调事件增加到IOLoop事件监听队列中,才可触发回调函数
def parse_body(body): """ 解析请求返回值,异步回调函数 :param body: :return: """ print("函数被回调") for line in json.loads(body.decode(encoding=‘utf8‘)): print(line) def asynchronous_fetch(url, callback): """ 异步请求方法,带回调函数 :param url: :param callback: :return: """ http_client = AsyncHTTPClient() def handle_response(response): callback(response.body) http_client.fetch(url, callback=handle_response) # 注意此处,需要启动IOLoop实例才能触发回调 IOLoop.instance().start() if __name__ == ‘__main__‘: url = "http://localhost:8080/rest/menu" # 异步请求,带回调函数 # asynchronous_fetch(url, callback=parse_body)
c、IOLoop提供了专门的方法add_future()来注册Futrue的回调事件,代码中应用了lamada表达式
def futrue_callback(res_future): print("调用回调函数 Futrue") parse_body(res_future._result.body) def async_fetch_future(url): """ 异步请求,使用Future类 :param url: :return: """ http_client = AsyncHTTPClient() my_future = Future() fetch_future = http_client.fetch(url) fetch_future.add_done_callback( # Future的result默认为HttpResponce lambda f: my_future.set_result(f.result())) return my_future if __name__ == ‘__main__‘: url = "http://localhost:8080/rest/menu" # 异步请求,返回Futrue类 future = async_fetch_future(url) io_loop = IOLoop.current() io_loop.add_future(future, callback=futrue_callback) io_loop.start()
d、@gen.coroutine实现了对Future内部回调的封装,因此使用@gen.conroutine使代码更加清晰,内部机制未变,因此调用方式未变
def parse_body(body): """ 解析请求返回值,异步回调函数 :param body: :return: """ print("函数被回调") for line in json.loads(body.decode(encoding=‘utf8‘)): print(line) def futrue_callback(res_future): print("调用回调函数 Futrue") parse_body(res_future._result.body) @gen.coroutine def fetch_coroutine(url): http_client = AsyncHTTPClient() response = yield http_client.fetch(url) return response if __name__ == ‘__main__‘: url = "http://localhost:8080/rest/menu" # 使用协程调用 gen_future = fetch_coroutine(url) io_loop = IOLoop.current() io_loop.add_future(gen_future, callback=futrue_callback) io_loop.start()
下一步需要深入学习的是:
1、IOLoop的实现原理与事件注册机制
标签:
原文地址:http://my.oschina.net/zhgk/blog/406394