1、tornado概述
Tornado就是我们在 FriendFeed 的 Web 服务器及其常用工具的开源版本。Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对epoll的运用,Tornado 每秒可以处理数以千计的连接,因此 Tornado 是实时 Web 服务的一个 理想框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题,请参阅The C10K problem)
Tornado代表嵌入实时应用中最新一代的开发和执行环境。 Tornado 包含三个完整的部分:
(1)、Tornado系列工具, 一套位于主机或目标机上强大的交互式开发工具和使用程序;
(2)、VxWorks 系统, 目标板上高性能可扩展的实时操作系统;
(3)、可选用的连接主机和目标机的通讯软件包 如以太网、串行线、在线仿真器或ROM仿真器。
2、tornado特点
Tornado的独特之处在于其所有开发工具能够使用在应用开发的任意阶段以及任何档次的硬件资源上。而且,完整集的Tornado工具可以使开发人员完全不用考虑与目标连接的策略或目标存储区大小。Tornado 结构的专门设计为开发人员和第三方工具厂商提供了一个开放环境。已有部分应用程序接口可以利用并附带参考书目,内容从开发环境接口到连接实现。Tornado包括强大的开发和调试工具,尤其适用于面对大量问题的嵌入式开发人员。这些工具包括C和C++源码级别的调试器,目标和工具管理,系统目标跟踪,内存使用分析和自动配置. 另外,所有工具能很方便地同时运行,很容易增加和交互式开发。
3、tornado模块索引
最重要的一个模块是web
, 它就是包含了 Tornado 的大部分主要功能的 Web 框架。其它的模块都是工具性质的, 以便让 web
模块更加有用 后面的 Tornado 攻略 详细讲解了 web
模块的使用方法。
主要模块
web
- FriendFeed 使用的基础 Web 框架,包含了 Tornado 的大多数重要的功能escape
- XHTML, JSON, URL 的编码/解码方法database
- 对MySQLdb
的简单封装,使其更容易使用template
- 基于 Python 的 web 模板系统httpclient
- 非阻塞式 HTTP 客户端,它被设计用来和web
及httpserver
协同工作auth
- 第三方认证的实现(包括 Google OpenID/OAuth、Facebook Platform、Yahoo BBAuth、FriendFeed OpenID/OAuth、Twitter OAuth)locale
- 针对本地化和翻译的支持options
- 命令行和配置文件解析工具,针对服务器环境做了优化
底层模块
httpserver
- 服务于web
模块的一个非常简单的 HTTP 服务器的实现iostream
- 对非阻塞式的 socket 的简单封装,以方便常用读写操作ioloop
- 核心的 I/O 循环
4.tornado框架使用
1.基本用法
import tornado.web import tornado.ioloop class IndexHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.write("Hello World") application = tornado.web.Application([ (r'/index',IndexHandler), ]) if __name__ == "__main__": application.listen(8080) tornado.ioloop.IOLoop.instance().start()
第一步:执行脚本,监听 8080 端口
第二步:浏览器客户端访问 /index --> http://127.0.0.1:8080/index
第三步:服务器接受请求,并交由对应的类处理该请求
第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法
第五步:然后将类的方法返回给浏览器
5.tornado路由系统
在tornado web框架中,路由表中的任意一项是一个元组,每个元组包含pattern(模式)和handler(处理器)。当httpserver接收到一个http请求,server从接收到的请求中解析出url path(http协议start line中),然后顺序遍历路由表,如果发现url path可以匹配某个pattern,则将此http request交给web应用中对应的handler去处理。由于有了url路由机制,web应用开发者不必和复杂的http server层代码打交道,只需要写好web应用层的逻辑(handler)即可。Tornado中每个url对应的是一个类。
import tornado.web import tornado.ioloop class IndexHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.write("Hello World") class LoginHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.write("<input type = 'text'>") class RegisterHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): self.write("<input type = 'password'>") application = tornado.web.Application([ (r'/index/(?P<page>\d*)',IndexHandler), # 基础正则路由 (r'/login',LoginHandler), (r'/register',RegisterHandler), ]) # 二级路由映射 application.add_handlers('buy.zhangyanlin.com$',[ (r'/login', LoginHandler), ]) if __name__ == "__main__": application.listen(8080) tornado.ioloop.IOLoop.instance().start()
6.tornado 模板引擎
Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。
Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {%
和 %}
包起来的 例如 {% if len(items) > 2 %}
。表达语句是使用 {{
和 }}
包起来的,例如 {{ items[0] }}
。
控制语句和对应的 Python 语句的格式基本完全相同。我们支持 if
、for
、while
和 try
,这些语句逻辑结束的位置需要用 {% end %}
做标记。还通过 extends
和 block
语句实现了模板继承。这些在 template
模块 的代码文档中有着详细的描述。
注:在使用模板前需要在setting中设置模板路径:"template_path" : "views"
settings = { 'template_path':'views', #设置模板路径,设置完可以把HTML文件放置views文件夹中 'static_path':'static', # 设置静态模板路径,设置完可以把css,JS,Jquery等静态文件放置static文件夹中 'static_url_prefix': '/sss/', #导入时候需要加上/sss/,例如<script src="/sss/jquery-1.9.1.min.js"></script> 'cookie_secret': "asdasd", #cookie生成秘钥时候需提前生成随机字符串,需要在这里进行渲染 'xsrf_cokkies':True, #允许CSRF使用 } application = tornado.web.Application([ (r'/index',IndexHandler), ],**settings) #需要在这里加载
1、模板语言基本使用for循环,if..else使用,自定义UIMethod以UIModule
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import tornado.ioloop import tornado.web import uimodule as md import uimethod as mt INPUT_LIST = [] class MainHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): name = self.get_argument('xxx',None) if name: INPUT_LIST.append(name) self.render("index.html",npm = "NPM88888",xxoo = INPUT_LIST) def post(self, *args, **kwargs): name = self.get_argument('xxx') INPUT_LIST.append(name) self.render("index.html", npm = "NPM88888", xxoo = INPUT_LIST) # self.write("Hello, World!!!") settings = { 'template_path':'tpl', # 模板路径的配置 'static_path':'statics', # 静态文件路径的配置 'ui_methods':mt, # 自定义模板语言 'ui_modules':md, # 自定义模板语言 } #路由映射,路由系统 application = tornado.web.Application([ (r"/index",MainHandler), ],**settings) if __name__ == "__main__": # 运行socket application.listen(8000) tornado.ioloop.IOLoop.instance().start()
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1.可添加js,css等东西 """ from tornado.web import UIModule from tornado import escape class Custom(UIModule): #渲染到前端的函数 def render(self, val,*args, **kwargs): # #内部会进行转义 # return "<h1>lujiacheng</h1>" #告诉它不转义 return escape.xhtml_escape("<h1>lujiacheng</h1>") #嵌入CSS def embedded_css(self): pass # return "h1{display:None}" #导入CSS文件 #PS:需配置静态文件 def css_files(self): return "login.css" #嵌入js def embedded_javascript(self): pass # 导入javascript文件 # PS:需配置静态文件 def javascript_files(self): pass
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
def func(self,arg): return arg.lower()
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link type="text/css" rel="stylesheet" href="static/commons.css"> </head> <body> <script src="static/zhang.js"></script> <h1>Hello world</h1> <h1>My name is zhangyanlin</h1> <h1>输入内容</h1> <form action="/index" method="post"> <input type="text" name="xxx"> <input type="submit" value="提交"> </form> <h1>展示内容</h1> <h3>{{ npm }}</h3> <h3>{{ func(npm)}}</h3> <h3>{% module custom() %}</h3> <ul> {% for item in xxoo %} {% if item == "zhangyanlin" %} <li style="color: red">{{item}}</li> {% else %} <li>{{item}}</li> {% end %} {% end %} </ul> </body> </html>
2、母板继承
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>帅哥</title> <link href="{{static_url("css/common.css")}}" rel="stylesheet" /> {% block CSS %}{% end %} </head> <body> <div class="pg-header"> </div> {% block RenderBody %}{% end %} <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script> {% block JavaScript %}{% end %} </body> </html>
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{% extends 'layout.html'%} {% block CSS %} <link href="{{static_url("css/index.css")}}" rel="stylesheet" /> {% end %} {% block RenderBody %} <h1>Index</h1> <ul> {% for item in li %} <li>{{item}}</li> {% end %} </ul> {% end %} {% block JavaScript %} {% end %}
3、导入内容
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<div> <ul> <li>aaaa</li> <li>bbbbb</li> <li>cccccccccc</li> </ul> </div>
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>title</title> <link href="{{static_url("css/common.css")}}" rel="stylesheet" /> </head> <body> <div class="pg-header"> {% include 'header.html' %} </div> <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script> </body> </html>