废话不多说,直接上代码

__auth__ = "aleimu"
__doc__ = "学习tornado6.0+ 版本与python3.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的源码可以发现其中大部分函数都支持了类型检验,和返回值提示,值得阅读.

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. boa移植 boa交叉编译

    官网:http://www.boa.org/ BOA 服务器是一个小巧高效的web服务器,是一个运行于unix或linux下的,支持CGI的.适合于嵌入式系统的单任务的http服务器,源代码开放.性能 ...

  2. hashlib(hmac)进阶之client跟server交互

    首先我还是要强调不管任何相同的字符串通过hashlib加密之后都会产生相同的32位字符串,这个是日常Web中常用的加密算法如果我的client发送一个请求过来我server接受到后就要对该密码进行判断 ...

  3. pycharm 使用Git提交代码到Github

    pycharm 使用Git提交代码到Github pytharm 创建django项目,提交到github总是失败,在github创建项目拉下来后项目层级会多一层,为此查了一些资料,亲测如下方式可行. ...

  4. Linux 用epoll实现的简单http服务器

    Linux 用epoll实现的简单http服务器 main.c #include <stdio.h> #include <sys/types.h> #include <s ...

  5. SpringBoot使用Hibernate,实现自动创建数据库表【博客数据库设计】

    我们准备设计博客,那就要设计数据库. 我们可以使用Hibernate来自动生成数据库. 博客数据库的结构: 实体类: 博客 Blog 博客分类 Type 博客标签 Tag 博客评论 Comment 用 ...

  6. Nginx类

    nginx常见错误页面有哪些?对于其解决方法是什么? 404 bad request 请求失败,请求所希望得到的资源未被在服务器上发现.没有信息能够告诉用户这个状况到底是暂时的还是永久的.假如服务器知 ...

  7. JAVAWEB复习笔记-day02

    1.CSS样式优先级 优先级:由上到下,由外到内.优先级越来越高 2.css选择器 html标签选择器 class选择器(.) id选择器(#) 3.优先级 style属性>id选择器>c ...

  8. Rust中的字符串处理

    一路看过来,怕是我知道的所有语言当,处理最复杂吧. 当然,如果能正确处理,也是能理解最到位的. 这,就是我为什么要学Rust的原因. 暂无用武之地,但逻辑体系和知识点够复杂,才能应对更多事务~ fn ...

  9. python 函数,模块知识点运用示例

    给定验证码长度n,生成随机验证码,验证码由数字.字母组成(参考chr()内置方法) # 给定验证码长度n,生成随机验证码,验证码由数字.字母组成(参考chr()内置方法) # 第33-126号(共94 ...

  10. centos7编译安装php 遇到的问题

    centos7 编辑安装php遇到的问题: ./configure 配置遇到的No package 'libxml-2.0' found缺失libxml2.0 库,解决方法: yum -y insta ...