tornado用户指引系列:协程异步
#1.同步tornado from tornado.httpclient import HTTPClient def synchronous_fetch(url): http_client = HTTPClient() response = http_client.fetch(url) return response.body #2.1回调函数实现的异步 from tornado.httpclient import AsyncHTTPClient def asynchronous_fetch(url, callback): http_client = AsyncHTTPClient() def handle_response(response): callback(response) http_client.fetch(url, callback=handle_response) #2.2回调函数实现的异步 from tornado.concurrent import Future def asynchronous_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 #3.协程实现的异步 from tornado import gen @gen.coroutine def fetch_coroutine(url): http_client = AsyncHTTPClient() response = yield http_client.fetch(url) return response.body # python2.7,python3.3不支持将生成器函数作为返回值 # 为了克服这个,Tornado coroutines抛出一个特殊种类的异常,称为Return. # raise gen.Return(response.body)
tornado官方建议,使用协程实现的异步。
tornado协程实现的异步,还可以有不同的调用方式,具体分为:
# 1.调用阻塞函数 # 调用阻塞函数最简单的办法是通过使用线程池ThreadPoolExecutor,它会返回一个Future. #线程池使用方式一:thread_pool.submit from concurrent.futures import ThreadPoolExecutor thread_pool = ThreadPoolExecutor(4) @gen.coroutine def call_blocking(): yield thread_pool.submit(blocking_func, args) #线程池使用方式一: run_on_executor装饰器 from tornado.concurrent import run_on_executor class IndexHandler(BaseHandler): executor = ThreadPoolExecutor(4) @gen.coroutine def get(self): res = yield self.back_handle() self.set_header("Content-Type", "application/json") self.finish(res) @gen.coroutine def post(self, *args, **kwargs): res = yield self.back_handle() self.set_header("Content-Type", "application/json") self.finish(res) @run_on_executor def back_handle(self): res = "blocking-func something........." return res import tornado.web class BaseHandler(tornado.web.RequestHandler): def data_received(self, chunk): u"""不知道干嘛的,不实现这个会有异常提醒。先放着""" pass def __init__(self, *argc, **argkw): super(BaseHandler, self).__init__(*argc, **argkw) def get_connect(self, conn_name): return self.application.get_connect(conn_name) def set_default_header(self): self.set_header('Access-Control-Allow-Origin', '*') self.set_header('Access-Control-Allow-Headers', 'x-requested-with') self.set_header('Access-Control-Allow-Methods', 'POST, GET') #2.并行 # coroutine装饰器能够识别Future的列表或字典,能够并行执行它们并等待全部完成。 @gen.coroutine def parallel_fetch(url1, url2): http_client = AsyncHTTPClient() resp1, resp2 = yield [http_client.fetch(url1), http_client.fetch(url2)] @gen.coroutine def parallel_fetch_many(urls): http_client = AsyncHTTPClient() responses = yield [http_client.fetch(url) for url in urls] # responses is a list of HTTPResponses in the same order @gen.coroutine def parallel_fetch_dict(urls): http_client = AsyncHTTPClient() responses = yield {url: http_client.fetch(url) for url in urls} # responses is a dict {url: HTTPResponse} #3.在yield前插入其它代码 # 有时候,你需要暂存一个Future而不立即yield它。在此之前可以执行一些其它操作。 @gen.coroutine def get(self): fetch_future = self.fetch_next_chunk() while True: chunk = yield fetch_future #这里对取到的Future执行yield if chunk is None: break self.write(chunk) fetch_future = self.fetch_next_chunk() #先得到Future而不立刻对其yield yield self.flush() #4.循环 # 由于在python没有办法对for和while循环的每次迭代yield并同时获取结果,所以在循环中使用协程需要一些技巧。 # 你需要将循环条件和访问结果分开进行,下面的例子演示了这一点: # motor是一个mongodb的python api,它的实现也是基于协程方式,可以十分方便地在tornado中使用它。 import motor db = motor.MotorClient().test @gen.coroutine def loop_example(collection): cursor = db.collection.find() while (yield cursor.fetch_next): doc = cursor.next_object() #5.在后台定期地执行 # PeriodicCallback(用于定期地执行一个函数)在协程中并不十分常用。 # 你可以在协程中使用一个循环,在循环中使用tornado.gen.sleep达到同样的效果。 @gen.coroutine def minute_loop(): while True: yield do_something() yield gen.sleep(60) # Coroutines that loop forever are generally started with # spawn_callback(). IOLoop.current().spawn_callback(minute_loop) # 有时候,你可能需要执行一个更复杂的循环逻辑。比如,上面的例子中循环体每60+N s运行一次,N是do_something()函数执行的时间.如果你想精确控制每次循环执行时间为60s,你可以像下面这样做: @gen.coroutine def minute_loop2(): while True: nxt = gen.sleep(60) # 启动一个定时器并不yield它. yield do_something() # 在执行定时器的同时执行函数 yield nxt # 此时再等待定时器超时.
tornado(二):表单和模板
在tornado框架中,模板可以以{% if、for、函数、表达式、赋值 %}使用python语法!!! 在其它python框架中,是不可以的,使用的html语法。
Tornado用户指引(一)-----------异步和非阻塞I/O
tornado用户指引(二)------------tornado协程实现原理和使用(一)
https://www.cnblogs.com/b02330224/p/10200902.html
tornado用户指引(三)------tornado协程使用和原理(二)
https://blog.csdn.net/happyAnger6/article/details/51277407
tornado用户指引(四)------tornado协程使用和原理(三)
https://blog.csdn.net/happyAnger6/article/details/51291221
tornado用户指引(五)------- 一个并发的web爬虫:
https://blog.csdn.net/happyAnger6/article/details/51292536
tornado用户指引(六)------Tornado web应用程序结构(一)之Applicaton对象
https://blog.csdn.net/happyAnger6/article/details/51296018
posted on 2017-08-07 20:58 myworldworld 阅读(210) 评论(0) 收藏 举报
浙公网安备 33010602011771号