内容简介:On Python 3, IOLoop is always a wrapper around the asyncio event loop.这是我重新复习tornado的原因,tornado放弃了之前自己实现的tornado.ioloop,全面拥抱asyncio的event_loop.这个改动是非常大的,而且阅读tornado的源码可以发现其中大部分函数都支持了类型检验,和返回值提示,值得阅读.
废话不多说,直接上代码
__auth__ = "aleimu" __doc__ = "学习tornado6.0+ 版本与 python 3.7+" import time import asyncio import tornado.gen import tornado.web import tornado.ioloop import tornado.httpserver # tornado的HTTP服务器实现 from tornado.options import define, options from tornado.httpclient import HTTPClient, AsyncHTTPClient from requests import get settings = {'debug': True} url = "http://127.0.0.1:5000/" # 这是另个服务,请求5s后返回结果 # RuntimeError: Cannot run the event loop while another loop is running # 解释:HTTPClient内部写 loop.run_xxx,因为那是启动event loop的命令,通常只再最最最外面用一次,之后的代码都应假设 loop 已经在运转了。 def synchronous_fetch(url): print("synchronous_fetch") try: http_client = HTTPClient() time.sleep(5) response = http_client.fetch(url) print(response.body) except Exception as e: print("Error: " + str(e)) return str(e) http_client.close() return response.body # 替代synchronous_fetch的同步请求,没有内置loop.run_xxx def synchronous_get(url): response = get(url) time.sleep(5) print("synchronous_fetch") return response.text # 简单的模拟异步操作,这里之后应该替换成各种异步库的函数 async def sleep(): print("start sleep") await asyncio.sleep(5) print("end sleep") # 异步请求 async def asynchronous_fetch(url): http_client = AsyncHTTPClient() response = await http_client.fetch(url) print("asynchronous_fetch") return response.body # 测试 class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world:%s" % self.request.request_time()) self.finish() print("not finish!") return # 同步阻塞 class synchronous_fetcher(tornado.web.RequestHandler): def get(self): self.write("%s,%s" % (synchronous_fetch(url), self.request.request_time())) # 同步阻塞 class synchronous_geter(tornado.web.RequestHandler): def get(self): self.write("%s,%s" % (synchronous_get(url), self.request.request_time())) # 异步阻塞,我以为curl "127.0.0.1:8888/1" 总耗时希望为5s,可是是25s,看来异步没搞好,以下的函数都是基于此改进的 class asynchronous_fetcher_1(tornado.web.RequestHandler): async def get(self): body = await asynchronous_fetch(url) for i in range(3): print("skip %s" % i) await tornado.gen.sleep(5) time.sleep(5) print("end request") self.write("%s,%s" % (body, self.request.request_time())) # curl "127.0.0.1:8888/1" # b'{\n "data": "123"\n}\n',25.026000022888184 # 异步阻塞,效果同上,这里只是证明 tornado.gen.sleep(5)和asyncio.sleep(5) 效果一致 class asynchronous_fetcher_2(tornado.web.RequestHandler): async def get(self): body = await asynchronous_fetch(url) # 关注协程完成后返回的结果 for i in range(3): print("skip %s" % i) await sleep() time.sleep(5) print("end request") self.write("%s,%s" % (body, self.request.request_time())) # curl "127.0.0.1:8888/2" # b'{\n "data": "123"\n}\n',25.039999961853027 # 异步非阻塞-将部分异步操作放入组中,实现loop管理 class asynchronous_fetcher_3(tornado.web.RequestHandler): async def get(self): body = await asynchronous_fetch(url) await asyncio.wait([sleep() for i in range(3)]) print("end request") self.write("%s,%s" % (body, self.request.request_time())) # curl "127.0.0.1:8888/3" # b'{\n "data": "123"\n}\n',10.001000165939331 # 异步非阻塞-将所有异步操作放入组中,实现loop管理 class asynchronous_fetcher_4(tornado.web.RequestHandler): async def get(self): task_list = [sleep() for i in range(3)] task_list.append(asynchronous_fetch(url)) body = await asyncio.wait(task_list) # 将所有异步操作的结果返回,但是是无序的,要是需要返回结果的话解析起来比较麻烦 print("end request:", body) # print(type(body), len(body),type(body[0]),len(body[0]),type(body[0])) self.write("%s,%s" % ([x.result() for x in body[0] if x.result() is not None][0], self.request.request_time())) # curl "127.0.0.1:8888/4" # b'{\n "data": "123"\n}\n',5.006999969482422 def make_app(): return tornado.web.Application([ (r"/", MainHandler), (r"/1", asynchronous_fetcher_1), (r"/2", asynchronous_fetcher_2), (r"/3", asynchronous_fetcher_3), (r"/4", asynchronous_fetcher_4), (r"/5", synchronous_fetcher), (r"/6", synchronous_geter), ], **settings) if __name__ == "__main__": print("server start!") app = make_app() server = tornado.httpserver.HTTPServer(app) server.bind(8888) server.start(1) # forks one process per cpu,windows上无法fork,这里默认为1 tornado.ioloop.IOLoop.current().start()
总结
1.Tornado使用单线程事件循环,写的不好,会阻塞的非常严重,比如synchronous_geter 2.flask+celery可以完成常见的异步任务 3.await语法只能出现在通过async修饰的函数中 4.可以看到tornado.gen.coroutine, tornado.concurrent.run_on_executor,tornado.web.asynchronous,tornado.gen.coroutine等这些装饰器都不在经常使用了,都由async和await代替
参考文档:
https://zhuanlan.zhihu.com/p/27258289 # Python async/await入门指南 http://www.tornadoweb.org/en/stable/guide/intro.html # 这个官网 https://www.osgeo.cn/tornado/guide/intro.html #Tornado 1.0 - Tornado 6.0的更新说明,以及6.0版本的中文文档,适合英语不好的人阅读 https://www.osgeo.cn/tornado/releases/v5.0.0.html# 在Python 3上, IOLoop 总是包装asyncio事件循环。
On Python 3, IOLoop is always a wrapper around the asyncio event loop.
这是我重新复习tornado的原因,tornado放弃了之前自己实现的tornado.ioloop,全面拥抱asyncio的event_loop.这个改动是非常大的,
而且阅读tornado的源码可以发现其中大部分函数都支持了类型检验,和返回值提示,值得阅读.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 强大的姿势感知模型用于姿势不变的人脸识别
- 从姿势到图像——基于人体姿势引导的时尚图像生成算法
- 行人重识别告别辅助姿势信息,港中文、商汤等提出姿势无关的特征提取GAN
- 穿越边界的姿势
- 日志打印的正确姿势!
- 修复缺陷的正确姿势
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算群体智能基础
恩格尔伯里特 / 谭营 / 2009-10 / 69.00元
《计算群体智能基础》全面系统地介绍了计算群体智能中的粒子群优化(PSO)和蚁群优化(ACO)的基本概念、基本模型、理论分析及其应用。在简要介绍基本优化理论和总结各类优化问题之后,重点介绍了社会网络结构如何在个体间交换信息以及个体聚集行为如何形成一个功能强大的有机体。在概述了进化计算后,重点论述了粒子群优化和蚁群优化的基本模型及其各种变体,给出了分析粒子群优化模型的一种通用方法,证明了基于蚂蚁行为实......一起来看看 《计算群体智能基础》 这本书的介绍吧!