废话不多说,直接上代码

  1. __auth__ = "aleimu"
  2. __doc__ = "学习tornado6.0+ 版本与python3.7+"
  3. import time
  4. import asyncio
  5. import tornado.gen
  6. import tornado.web
  7. import tornado.ioloop
  8. import tornado.httpserver # tornado的HTTP服务器实现
  9. from tornado.options import define, options
  10. from tornado.httpclient import HTTPClient, AsyncHTTPClient
  11. from requests import get
  12. settings = {'debug': True}
  13. url = "http://127.0.0.1:5000/" # 这是另个服务,请求5s后返回结果
  14. # RuntimeError: Cannot run the event loop while another loop is running
  15. # 解释:HTTPClient内部写 loop.run_xxx,因为那是启动event loop的命令,通常只再最最最外面用一次,之后的代码都应假设 loop 已经在运转了。
  16. def synchronous_fetch(url):
  17. print("synchronous_fetch")
  18. try:
  19. http_client = HTTPClient()
  20. time.sleep(5)
  21. response = http_client.fetch(url)
  22. print(response.body)
  23. except Exception as e:
  24. print("Error: " + str(e))
  25. return str(e)
  26. http_client.close()
  27. return response.body
  28. # 替代synchronous_fetch的同步请求,没有内置loop.run_xxx
  29. def synchronous_get(url):
  30. response = get(url)
  31. time.sleep(5)
  32. print("synchronous_fetch")
  33. return response.text
  34. # 简单的模拟异步操作,这里之后应该替换成各种异步库的函数
  35. async def sleep():
  36. print("start sleep")
  37. await asyncio.sleep(5)
  38. print("end sleep")
  39. # 异步请求
  40. async def asynchronous_fetch(url):
  41. http_client = AsyncHTTPClient()
  42. response = await http_client.fetch(url)
  43. print("asynchronous_fetch")
  44. return response.body
  45. # 测试
  46. class MainHandler(tornado.web.RequestHandler):
  47. def get(self):
  48. self.write("Hello, world:%s" % self.request.request_time())
  49. self.finish()
  50. print("not finish!")
  51. return
  52. # 同步阻塞
  53. class synchronous_fetcher(tornado.web.RequestHandler):
  54. def get(self):
  55. self.write("%s,%s" % (synchronous_fetch(url), self.request.request_time()))
  56. # 同步阻塞
  57. class synchronous_geter(tornado.web.RequestHandler):
  58. def get(self):
  59. self.write("%s,%s" % (synchronous_get(url), self.request.request_time()))
  60. # 异步阻塞,我以为curl "127.0.0.1:8888/1" 总耗时希望为5s,可是是25s,看来异步没搞好,以下的函数都是基于此改进的
  61. class asynchronous_fetcher_1(tornado.web.RequestHandler):
  62. async def get(self):
  63. body = await asynchronous_fetch(url)
  64. for i in range(3):
  65. print("skip %s" % i)
  66. await tornado.gen.sleep(5)
  67. time.sleep(5)
  68. print("end request")
  69. self.write("%s,%s" % (body, self.request.request_time()))
  70. # curl "127.0.0.1:8888/1"
  71. # b'{\n "data": "123"\n}\n',25.026000022888184
  72. # 异步阻塞,效果同上,这里只是证明 tornado.gen.sleep(5)和asyncio.sleep(5) 效果一致
  73. class asynchronous_fetcher_2(tornado.web.RequestHandler):
  74. async def get(self):
  75. body = await asynchronous_fetch(url) # 关注协程完成后返回的结果
  76. for i in range(3):
  77. print("skip %s" % i)
  78. await sleep()
  79. time.sleep(5)
  80. print("end request")
  81. self.write("%s,%s" % (body, self.request.request_time()))
  82. # curl "127.0.0.1:8888/2"
  83. # b'{\n "data": "123"\n}\n',25.039999961853027
  84. # 异步非阻塞-将部分异步操作放入组中,实现loop管理
  85. class asynchronous_fetcher_3(tornado.web.RequestHandler):
  86. async def get(self):
  87. body = await asynchronous_fetch(url)
  88. await asyncio.wait([sleep() for i in range(3)])
  89. print("end request")
  90. self.write("%s,%s" % (body, self.request.request_time()))
  91. # curl "127.0.0.1:8888/3"
  92. # b'{\n "data": "123"\n}\n',10.001000165939331
  93. # 异步非阻塞-将所有异步操作放入组中,实现loop管理
  94. class asynchronous_fetcher_4(tornado.web.RequestHandler):
  95. async def get(self):
  96. task_list = [sleep() for i in range(3)]
  97. task_list.append(asynchronous_fetch(url))
  98. body = await asyncio.wait(task_list) # 将所有异步操作的结果返回,但是是无序的,要是需要返回结果的话解析起来比较麻烦
  99. print("end request:", body)
  100. # print(type(body), len(body),type(body[0]),len(body[0]),type(body[0]))
  101. self.write("%s,%s" % ([x.result() for x in body[0] if x.result() is not None][0],
  102. self.request.request_time()))
  103. # curl "127.0.0.1:8888/4"
  104. # b'{\n "data": "123"\n}\n',5.006999969482422
  105. def make_app():
  106. return tornado.web.Application([
  107. (r"/", MainHandler),
  108. (r"/1", asynchronous_fetcher_1),
  109. (r"/2", asynchronous_fetcher_2),
  110. (r"/3", asynchronous_fetcher_3),
  111. (r"/4", asynchronous_fetcher_4),
  112. (r"/5", synchronous_fetcher),
  113. (r"/6", synchronous_geter),
  114. ], **settings)
  115. if __name__ == "__main__":
  116. print("server start!")
  117. app = make_app()
  118. server = tornado.httpserver.HTTPServer(app)
  119. server.bind(8888)
  120. server.start(1) # forks one process per cpu,windows上无法fork,这里默认为1
  121. tornado.ioloop.IOLoop.current().start()

总结

  1. 1.Tornado使用单线程事件循环,写的不好,会阻塞的非常严重,比如synchronous_geter
  2. 2.flask+celery可以完成常见的异步任务
  3. 3.await语法只能出现在通过async修饰的函数中
  4. 4.可以看到tornado.gen.coroutine, tornado.concurrent.run_on_executor,tornado.web.asynchronous,tornado.gen.coroutine等这些装饰器都不在经常使用了,都由asyncawait代替

参考文档:

  1. https://zhuanlan.zhihu.com/p/27258289 # Python async/await入门指南
  2. http://www.tornadoweb.org/en/stable/guide/intro.html # 这个官网
  3. https://www.osgeo.cn/tornado/guide/intro.html #Tornado 1.0 - Tornado 6.0的更新说明,以及6.0版本的中文文档,适合英语不好的人阅读
  4. 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的源码可以发现其中大部分函数都支持了类型检验,和返回值提示,值得阅读.

tornado6与python3.7,异步新姿势的更多相关文章

  1. Python一键转Jar包,Java调用Python新姿势!

    粉丝朋友们,不知道大家看故事看腻了没(要是没腻可一定留言告诉我^_^),今天这篇文章换换口味,正经的来写写技术文.言归正传,咱们开始吧! 本文结构: 需求背景 进击的Python Java和Pytho ...

  2. 【转+自己研究】新姿势之Docker Remote API未授权访问漏洞分析和利用

    0x00 概述 最近提交了一些关于 docker remote api 未授权访问导致代码泄露.获取服务器root权限的漏洞,造成的影响都比较严重,比如 新姿势之获取果壳全站代码和多台机器root权限 ...

  3. FJNU 1159 Fat Brother’s new way(胖哥的新姿势)

    FJNU 1159 Fat Brother’s new way(胖哥的新姿势) Time Limit: 1000MS   Memory Limit: 257792K [Description] [题目 ...

  4. 相比于python2.6,python3.0的新特性。

    这篇文章主要介绍了相比于python2.6,python3.0的新特性.更详细的介绍请参见python3.0的文档. Common Stumbling Blocks 本段简单的列出容易使人出错的变动. ...

  5. Broadcom BCM94352z/DW1560驱动新姿势

    转自:https://blog.daliansky.net/Broadcom-BCM94352z-DW1560-drive-new-posture.html Broadcom WiFi/BlueToo ...

  6. vue组件通信新姿势

    在vue项目实际开发中我们经常会使用props和emit来进行子父组件的传值通信,父组件向子组件传递数据是通过prop传递的, 子组件传递数据给父组件是通过$emit触发事件来做到的.例如: Vue. ...

  7. JSON CSRF新姿势

    以前做渗透测试,遇到过很多次POST数据为JSON数据的CSRF,一直没有搞定,最近发现一个新姿势, ​​​本文作者:Mannix@安全文库 微信公众号:安全文库 测试的时候,当应用程序验证了Cont ...

  8. bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)

      题目大意:一个n*m的图中,“.”可走,“X”不可走,“*”为起点,问从起点开始绕所有X一圈回到起点最少需要走多少步. 一开始看到这题,自己脑洞了下怎么写,应该是可过,然后跑去看了题解,又学会了一 ...

  9. Java计时新姿势

    为获得更好的阅读体验,请访问原文:传送门 前言: 最近公司来了个大佬,从他那里学到不少东西,其中一个就是计时 的新姿势「StopWatch」,赶紧来一起了解了解吧! 一.最简单的计时 在我们的程序中不 ...

随机推荐

  1. 微信小程序滚动tab的实现

    微信小程序滚动tab的实现 1.目的:为了解决滚动版本的tab,以及实现虹吸效果. 2.方案:自己动手写了一个Demo,用于测试实现如上的效果.其代码有做参考,在这里先声明.具体的参照如下:重庆大学二 ...

  2. SQL Server学习内容(一)

    SQL Server SQL Server对大小写不敏感,每条语句末端使用分号. 1.SQL命令 SELECT 从数据中提取数据 UPDATE 更新数据中的数据 DELETE 从数据库中删除数据 IN ...

  3. [PHP] 广度优先搜索匹配网站所有链接

    <?php define('PRE_DOMAIN','www'); define('DOMAIN','sina.com.cn'); define('PROTOCOL','https'); def ...

  4. shell 字符菜单管理

    1.创建一个脚本func.sh 脚本如下func2.sh #!/bin/bash function menu(){ title="My Menu" url="www.la ...

  5. 201971010110-李华《面向对象程序设计(java)》第七周学习总结

    博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...

  6. ubuntu16.04安装docker图形管理界面portainer

    下载镜像 docker pull portainer/portainer 单机版运行 docker run -d --name portainer \ -p 9000:9000 \ --restart ...

  7. python27期day15:自定义模块、模块导入、模块的路径、模块的查找顺序、time、datetime、random、os、sys、作业题

    1.模块的介绍: py文件就是一个模块 2.模块的分类:内置模块:python标准库 200 第三方模块 自定义模块 3.为什么学习模块? 开发效率高,内置函数和模块 减少重复代码,分文件管理,有助于 ...

  8. 【Spring Data JPA篇】JPA的底层原理(二)

    一.接口继承结构 二.底层原理

  9. JDOJ 2174 忠诚

    JDOJ 2174 忠诚 https://neooj.com/oldoj/problem.php?id=2174 洛谷 P1816 忠诚 https://www.luogu.org/problemne ...

  10. hive数据库从文件插入数据得到结果NULL?

    今天第一次接触hive这个东东,跟着教程走,当把本地文件的数据装载到新建的hive的表中时,得到的结果是NULL,如图: 也不知道为什么,初次接触,对它的这个构造还不是很熟悉,看一下建表语句: 解决: ...