目录:Tornado其他篇

01: tornado基础篇

02: tornado进阶篇

03: 自定义异步非阻塞tornado框架

04: 打开tornado源码剖析处理过程

目录:

  • 1.1 Tornado安装与基本使用
  • 1.2 tornado各种url写法
  • 1.3 配置settings & 获取get,post请求
  • 1.4 tornado渲染
  • 1.5 自定义UIMethod和UIModule: 类似于djando中simple_tag和自定义filter
  • 1.6 模板继承
  • 1.7 tornado多文件上传
  • 1.8 @gen.coroutine实现异步非阻塞举例及原理解析

1.1 Tornado安装与基本使用     返回顶部

  1、 安装tornado

    1、pip3安装
        pip3 install tornado

    2、源码安装
        https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz

  2、tornado概述

      1、Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本

      2、Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。

      3、得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接

      4、我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里
           每一个活动用户都会保持着一个服务器连接。

  3、tornado快速上手

      1、使用pycharm创建一个普通项目s131415文件夹,并创建文件s131415/app.py
      2、在app.py中粘贴下列内容,运行app.py文件
      3、在浏览器中访问: http://127.0.0.1:8888/index 即可看到“Hello, world!!”请求内容

importtornado.ioloopimporttornado.web#1、 处理访问/index/的get请求: http://127.0.0.1:8888/index/
classMainHandler(tornado.web.RequestHandler):defget(self):self.write("I am index!!")#self.redirect('http://www.baidu.com')#self.render('index.html',k1='v1')#2、 处理访问 /login/的post请求和get请求: http://127.0.0.1:8888/login/
classLoginHandler(tornado.web.RequestHandler):defget(self):self.write('login')def post(self,*args,**kwargs):self.write('login post')#3、 配置settings
settings ={'template_path': 'template',         #配置html文件模板位置'static_path': 'static',             #配置静态文件路径(图片等)'static_url_prefix': '/static/',     #前端引入静态文件路径
}#4 路由系统
application =tornado.web.Application([(r"/index/", MainHandler),(r"/login/", LoginHandler),
],**settings)#5 启动这个tornado这个程序
if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()

tornado基本使用

1.2 tornado各种url写法     返回顶部

  1、无正则匹配url  (http://127.0.0.1:8000/index/?nid=1&pid=2)

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):nid= self.get_query_argument('nid')pid= self.get_query_argument('pid')self.write("Hello, world")#http://127.0.0.1:8000/index/?nid=1&pid=2
application =tornado.web.Application([(r"/index/", MainHandler),
])if __name__ == "__main__":application.listen(8000)tornado.ioloop.IOLoop.instance().start()

app.py

  2、基于(\d+)正则的url

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self,nid,pid):print(nid,pid)self.write("Hello, world")#http://127.0.0.1:8000/index/1/2/
application =tornado.web.Application([(r"/index/(\d+)/(\d+)/", MainHandler),        #这种只能传数字#(r"/index/(\w+)/(\w+)/", MainHandler),        # 这种可以传数字、字母、下划线
])if __name__ == "__main__":application.listen(8000)tornado.ioloop.IOLoop.instance().start()

app.py

  3、基于正则分组(?P<nid>\d+),可以不考虑接收参数顺序 (推荐)

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self,nid,pid):print(nid,pid)self.write("Hello, world")#http://127.0.0.1:8000/index/1/2/
application =tornado.web.Application([(r"/index/(?P<nid>\d+)/(?P<pid>\d+)/", MainHandler),        #这种只能传数字
])if __name__ == "__main__":application.listen(8000)tornado.ioloop.IOLoop.instance().start()

app.py

1.3 配置settings & 获取get,post请求     返回顶部

  1、settings可配置参数

settings ={'template_path': 'template',        #配置html文件模板位置'static_path': 'static',             #配置静态文件路径(图片等)'static_url_prefix': '/static/',    #前端引入静态文件路径'ui_methods': mt,'ui_modules': md,'xsrf_cookies':True,'cookie_secret':'xxx','login_url':"/auth/login",'autoescape':None,'local':"zh_CN",'debug':True,
}

tornado中settings字典可配置参数

  2、获取get、post请求

importtornado.ioloopimporttornado.web#1、 处理访问/index/的get请求: http://127.0.0.1:9999/index
classMainHandler(tornado.web.RequestHandler):defget(self):self.write("I am index!!")#self.redirect('http://www.baidu.com')#self.render('index.html',k1='v1')#2、 处理访问 /login/的post请求和get请求: http://127.0.0.1:9999/login
classLoginHandler(tornado.web.RequestHandler):defget(self):#2.1 获取url中以get方式传递过来的数据: http://127.0.0.1:9999/login/?username=zhangsan#print(self.get_query_argument('username'))        # zhangsan#print(self.get_query_arguments('username'))       # ['zhangsan']#print( self.get_argument('username') )            # get和post两种请求传递的数据都能获取
self.render('login.html')def post(self,*args,**kwargs):#2.2 获取请求体中以post传递的数据#print( self.get_body_argument('faver') )     # 仅能获取单选,多选仅能获取最后一个#print( self.get_body_arguments('faver') )    # ['1', '2', '3']  获取多选#2.3 get和post两种请求传递的数据都能获取#print( self.get_argument('username') )#2.4 设置和获取cookie#self.cookies#self.set_cookie()#2.5 设置和获取请求头#self._headers#self.get_header()
self.write('login post')#3、 配置settings
settings ={'template_path': 'template',         #配置html文件模板位置'static_path': 'static',             #配置静态文件路径(图片等)'static_url_prefix': '/static/',     #前端引入静态文件路径
}#4 路由系统
application =tornado.web.Application([(r"/index/", MainHandler),(r"/login/", LoginHandler),
],**settings)#5 启动这个tornado这个程序
if __name__ == "__main__":application.listen(9999)tornado.ioloop.IOLoop.instance().start()

app.py

<!DOCTYPE html>
<htmllang="en">
<head><metacharset="UTF-8"><title>Title</title><linkrel="stylesheet"href="/static/base.css">
</head>
<body><formmethod="POST"action="/login/"><inputtype="text"name="username"><h5class="c1">多选</h5>男球:<inputtype="checkbox"name="faver"value="1" />足球:<inputtype="checkbox"name="faver"value="2" />皮球:<inputtype="checkbox"name="faver"value="3" /><inputtype="submit"value="提交"></form>
</body>
</html>

/template/login.html

.c1{color:red;
}

/template/base.css

1.4 tornado渲染     返回顶部

  1、for循环

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):self.render("index.html", username='tom',list_info=[11, 22, 33],user_dic={'username':'zhangsan','age':77})application=tornado.web.Application([(r"/index", MainHandler),
])if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()

app.py

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h3>用户名:{{username}}</h3>{% for item in list_info %}<li>{{item}}</li>{% end %}<p></p>{% for item in user_dic %}<li>{{item}} : {{user_dic[item]}}</li>{% end %}</body>
</html>

index.html

  2、if、in、判断相等

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):self.render("index.html", list_info=[11, 22, 33],username='tom')application=tornado.web.Application([(r"/index", MainHandler),
])if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()

app.py

<!DOCTYPE html>
<htmllang="en">
<head><metacharset="UTF-8"><title>Title</title>
</head>
<body>{% if 11 in list_info %}true{% else %}false{% end %}{% if username == "tom" %}my name is {{username}}{% else %}not tom{% end %}</body>
</html>

index.html

1.5 自定义UIMethod和UIModule: 类似于djando中simple_tag和自定义filter      返回顶部

  1、UIModule与UIMethod比较

      1. UIModule: 可以传参、可以生成html、css、js代码

      2. UIMethod: 这个不能传参数,不能生成css,js等,只能生成html文件

  2、UIModule和UIMethod使用举例

importtornado.ioloopimporttornado.webfrom tornado.escape importlinkifyimport uimodules as md     #1.导入uimodules模块
import uimethods as mt     #2.导入uimethods模块classMainHandler(tornado.web.RequestHandler):defget(self):self.render('index.html')
settings={'template_path': 'template','static_path': 'static','static_url_prefix': '/static/','ui_methods': mt,      #3.将uimethods模块注册到settings中'ui_modules': md,      #4.将uimodules模块注册到settings中
}application=tornado.web.Application([(r"/index", MainHandler),
],**settings)if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()

app.py注册

from tornado.web importUIModulefrom tornado importescape#uimodule不仅可以帮生成标签,还可以帮添加css,js样式
classcustom(UIModule):#def javascript_files(self):#'''1、生成: <script src="base.js"></script> '''#return ['base.js','header.js']#   #def embedded_javascript(self):#'''2、生成:  <script> alert(123); </script> '''#return "alert(123);"#   #def css_files(self):#'''3、在头部生成: <link rel="stylesheet" href="base.css">'''#return ['base.css','header.css']#   #def embedded_css(self):#'''4、在头部style标签生成: <style> .c1{ color:red; } </style>'''#return ".c1{color:red;}"def render(self, *args, **kwargs):'''5、生成html文件'''return escape.xhtml_escape('<h1>tom</h1>')

uimodules.py定义

deftab(self):return '<h1>tom</h1>'

uimethods.py定义

<!DOCTYPE html>
<htmllang="en">
<head><metacharset="UTF-8"><title>Title</title>
</head>
<body><h1>hello</h1><p>{% module custom(123) %}</p>{{ tab() }}</body>
</html>

index.html使用

1.6 模板继承     返回顶部

   1、模板继承使用

      1. 在master.html中定义模板:  {% block css %} {% endblock %}

      2. 在子类中引入要继承的模板:  {% extends 'layout.html' %}

   2、模板导入

      1. 使用时直接导入即可:  {% include "header.html" %}

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):self.render("index.html")settings={'template_path':'template','static_path':'static','static_url_prefix':'/static/',
}application=tornado.web.Application([(r"/index/", MainHandler),
],**settings)if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()

app.py

<!DOCTYPE html>
<htmllang="en">
<head><metacharset="UTF-8"><title>Title</title><title>{% block title %}Default title{% end %}</title><linkrel="stylesheet"href="/static/css/base.css">{% block css %}{% end %}</head>
<body><divclass="c1">这里是layout.html这个母版中的内容</div>{% block RenderBody %}{% end %}</body>
</html>

layout.html 母版文件

{% extends 'layout.html'%}
{% block css %}<linkrel="stylesheet"href="/static/css/index.css">{% end %}{% block RenderBody %}<h3class="c1">这个RenderBody块继承的是header.html这个母版</h3><div>{% include 'header.html' %}</div>{% end %}

index.html 子版中引入母版

<h3>这里是header.html中的内容,需要导入的文件</h3>

header.html 被导入的文件

1.7 tornado多文件上传      返回顶部

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):self.render('index.html')def post(self, *args, **kwargs):file_metas= self.request.files["fff"]for meta infile_metas:file_name= meta['filename']with open(file_name,'wb') as up:print('hahah')up.write(meta['body'])settings={'template_path': 'template',
}application=tornado.web.Application([(r"/index", MainHandler),
],**settings)if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()

app.py

<!DOCTYPE html>
<html>
<head><metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"/><title>上传文件</title>
</head>
<body><formid="my_form"name="form"action="/index"method="POST"enctype="multipart/form-data" ><inputname="fff"id="my_file"type="file" /><inputtype="submit"value="提交"  /></form>
</body>
</html>

index.html

1.8 @gen.coroutine实现异步非阻塞举例及原理解析     返回顶部

  1、tornado.gen.coroutine和tornado.web.asynchronous比较

      1. @tornado.web.asynchronous 实现长连接,调用self.finish()才结束
      2. @tornado.gen.coroutine 这个实现异步
      3. 你要想异步,就要保持长连接,否则你的handler执行完就自己return了
      4. @asynchronous会监听@gen.coroutine的返回结果(Future),并在@gen.coroutine装饰的代码段执行完成后自动调用finish。
      5. 从Tornado 3.1版本开始,只使用@gen.coroutine就可以了。

  2、tornado实现异步原理

      1. 每个请求过来就会创建一个socket对象,并yield一个future对象,然后tornado就处理下一个连接了
      2. tornado内部会以socket对象为key,future对象为value加入字典
      3. tornado内部调用epoll方法监听这个全局字典,有socket对象变化就会执行future.set_result('...')
      4. 执行future.set_result('...')后就会将future.ready标志位变成True,然后就会调用callback方法返回内容

      注1:yield 一个 Future对象,那么Tornado会等待,直到执行future.set_result('...')才会释放
      注2:epoll实质是不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程

importtornado.ioloopimporttornado.webfrom tornado importgenclassIndexHandler(tornado.web.RequestHandler):@gen.coroutinedefget(self):self.write('I am index!!')application=tornado.web.Application([(r"/index/", IndexHandler),
])if __name__ == "__main__":print('http://127.0.0.1:8888/index/')application.listen(8888)tornado.ioloop.IOLoop.instance().start()

tornado实现异步非阻塞举例

#! /usr/bin/env python#-*- coding: utf-8 -*-
importtornado.ioloopimporttornado.webfrom tornado importgenfrom tornado.concurrent importFuturefuture=NoneclassIndexHandler(tornado.web.RequestHandler):@gen.coroutinedefget(self):globalfuturefuture=Future()future.add_done_callback(self.doing)yieldfuturedef doing(self,*args,**kwargs):self.write('async')self.finish()classStopHandler(tornado.web.RequestHandler):defget(self):future.set_result('.......')application=tornado.web.Application([(r"/index/", IndexHandler),(r"/stop/", StopHandler),
])if __name__ == "__main__":print('http://127.0.0.1:8888/index/')application.listen(8888)tornado.ioloop.IOLoop.instance().start()'''http://127.0.0.1:8888/index/          # 只要不返回数据,浏览器就不会返回一直等着保持长连接
http://127.0.0.1:8888/stop/           # 访问/stop/是会调用future.set_result()此时 /index/就会返回数据'''

使用Future对象模拟tornado异步非阻塞简单原理

转载于:https://www.cnblogs.com/xiaonq/p/8026197.html

01: tornado基础篇相关推荐

  1. Arduino 高级教程 01:基础篇

    我与 Arduino,以及为什么要写这个系列的文章 Arduino 这个已经火了好多年了,早就不是什么新鲜的技术.如果有人还不清楚 Arduino 是个什么东西,对不起,请自行搜索,随便翻开哪个维基百 ...

  2. 视觉slam学习|基础篇01

    系列文章目录 SLAM基础篇01 SLAM基础篇02 目录 系列文章目录 前言 SLAM是干什么的? SLAM的数学建模 机器人学基础 齐次矩阵 关于旋转的表示:旋转向量.欧拉角.四元数 李群和李代数 ...

  3. mysql经典总结文章_MySQL基础篇(01):经典实用查询案例,总结整理

    MySQL基础篇(01):经典实用查询案例,总结整理 发布时间:2020-02-26 22:25:21 来源:51CTO 阅读:244 作者:知了一笑 本文源码:GitHub·点这里 || GitEE ...

  4. python 01列表异或_python基础篇三

    python基础篇二所介绍的列表是基本的数据类型之一,元组.集合.字典也是基本的数据类型之一.熟练运用这些基本的数据类型很重要,就像是一座高楼大厦,把地基打扎实了,这栋高楼大厦才能在狂风暴雨中岿然不动 ...

  5. 小何同学的leetcode刷题笔记 基础篇(01)整数反转

    小何同学的leetcode刷题笔记 基础篇(01)整数反转[07] *** [01]数学取余法*** 对数字进行数位操作时,常见的方法便是用取余的方法提取出各位数字,再进行操作 操作(1):对10取余 ...

  6. Jmeter 入门 从0-1 基础篇-实操

    Jmeter 入门 从0-1 基础篇 笔记有的图片链接可能失效了,等我修改好了在来编辑哈 文章目录 1 JMeter 1.1 JMeter环境搭建和基本使用 1.1.1 JMeter环境搭建 1.1. ...

  7. 01 MSC类设备-基础篇(一)

    一.简介 在USB协议中,规定了一类大容量存储设备(Mass Storage Device Class)协议.常见的USB大容量设备有:U盘.USB移动硬盘.USB移动光驱.USB读卡器.USB打印机 ...

  8. 01 - Java并发编程与高并发解决方案笔记-基础篇

    01 - Java并发编程与高并发解决方案笔记-基础篇 基础篇很重要!很重要!很重要!!!一定要理解和认真思考. 01 - Java并发编程与高并发解决方案笔记-基础篇 1.课程准备 2.并发编程基础 ...

  9. 自然语言处理——基础篇01

    自然语言处理--基础篇01 一.什么是自然语言处理? 二.自然语言处理的难点与特点? 三.语言模型 四.NLP的常见任务类型 1. 中文分词 2. 子词切分(Subword) 3. 句法分析 4. 语 ...

最新文章

  1. 架构师之路 — API 经济 — 身份认证系统
  2. MySQL学习笔记_9_MySQL高级操作(上)
  3. linux系统管理命令,压缩命令
  4. 在Delphi程序中应用IE浏览器控件
  5. 【Paper】英文论文写作小技巧
  6. make pycaffe 报错:“fatal error: numpy/arrayobject.h: No such file or directory” 解决方案
  7. 设计模式学习---(2)工厂模式
  8. MySQL 如何查找并删除重复行
  9. lightshot截图工具的安装及使用
  10. LoadRunner字符串编码转换函数:lr_convert_string_encoding
  11. python列表语法_python学习之列表语法
  12. 开源微信小程序源码+小程序游戏代码附搭建框架教程
  13. PRN(20201012):Improved updating of Euclidean distance maps and Voronoi diagrams
  14. 寺庙招聘爆火:月薪15000,五险一金,早九晚五,周末双休,饭菜免费!网友:想出家了......
  15. Web 中的“选区”和“光标”需求实现
  16. 离职后重回老东家?你需要明白这些事情
  17. 【对称日】今天朋友圈对称日刷屏了,也来凑个热闹,用代码实力打脸
  18. VMware虚拟机怎么安装ghost系统
  19. 什么是锁PHP,并发下常见的加锁及锁的PHP具体实现代码
  20. 微信H5支付(V3)

热门文章

  1. 帝国竞争算法(ICA)详解与python 实现
  2. 关于手写笔记、电子笔记、摘录的思考
  3. 闲谈个人品牌策划以及营销
  4. 关于微信开放平台开发者资质认证的简单记录
  5. Java线程共享变量
  6. poj3104 Drying(二分最大化最小值 好题)
  7. 省市县三级列表(jsp实现)
  8. 在OpenBSD上架设安全的小型网络
  9. 计算机桌面怎么突然变大了,电脑屏幕突然变大了怎么办
  10. 【python】秀人集-写真集-爬虫-2.0