Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。

Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web 服务来说,Tornado 是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。

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

一、快速上手

import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") application = tornado.web.Application([
(r"/index", MainHandler),
]) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

第一步:执行脚本,监听 8888 端口

第二步:浏览器客户端访问 /index  -->  http://127.0.0.1:8888/index

第三步:服务器接受请求,并交由对应的类处理该请求

第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法

第五步:方法返回值的字符串内容发送浏览器

 #!/usr/bin/env python
# -*- coding:utf-8 -*-
#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from tornado import httpclient
from tornado.web import asynchronous
from tornado import gen import uimodules as md
import uimethods as mt class MainHandler(tornado.web.RequestHandler):
@asynchronous
@gen.coroutine
def get(self):
print 'start get '
http = httpclient.AsyncHTTPClient()
http.fetch("http://127.0.0.1:8008/post/", self.callback)
self.write('end') def callback(self, response):
print response.body settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt,
'ui_modules': md,
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8009)
tornado.ioloop.IOLoop.instance().start()

异步非阻塞实例

二、路由系统

路由系统其实就是 url 和 类 的对应关系,这里不同于其他框架,其他很多框架均是 url 对应 函数,Tornado中每个url对应的是一个类。

import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") class StoryHandler(tornado.web.RequestHandler):
def get(self, story_id):
self.write("You requested the story " + story_id) class BuyHandler(tornado.web.RequestHandler):
def get(self):
self.write("buy.wupeiqi.com/index") application = tornado.web.Application([
(r"/index", MainHandler),
(r"/story/([0-9]+)", StoryHandler),
]) application.add_handlers('buy.wupeiqi.com$', [
(r'/index',BuyHandler),
]) if __name__ == "__main__":
application.listen(80)
tornado.ioloop.IOLoop.instance().start()

三、模板

Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。

Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}。表达语句是使用 {{ 和 }} 包起来的,例如 {{ items[0] }}

控制语句和对应的 Python 语句的格式基本完全相同。我们支持 ifforwhile 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块 的代码文档中有着详细的描述

 <!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>

layout

 {% 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 %}

index

import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('home/index.html') settings = {
'template_path': 'template',
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(80)
tornado.ioloop.IOLoop.instance().start()

四、使用

import tornado.ioloop
import tornado.web #视图
class MainHandle(tornado.web.RequestHandler):
def initialize(self):
print('') #在每一次请求开始先执行一下初始化这个方法
def get(self):
print(self.get_cookie('user'))
self.write('hello world') #默认有个return none
def post(self,*args,**kwargs):
pass class LoginHandle(tornado.web.RequestHandler):
def get(self,*args,**kwargs):
self.render('templates/login.html') #没有脱离文件路径的知识
def post(self,*args,**kwargs):
user = self.get_argument('user')
pwd = self.get_argument('pwd')
print(user,pwd)
if user=='haiyan' and pwd=='':
self.set_cookie('user','haiyan',10) #设置cookie,10秒后过期
self.set_secure_cookie('user','haiyan',) #签名cookie
self.redirect('/index') #要么return一下
else: #要么else分割开,不然会报错
self.render('templates/login.html')
# self.get_arguments() #getlist 像是复选框,一下取多个值 class TestHandle(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
sss = {'name':"haiyan","info":{'name':'小华','age':18},"li":[11,22,33]}
self.render('templates/test.html',**sss) settings={
'static_path':'static',
'xsrf_cookies':True,
'cookie_secret':''
}
#路由分配
application = tornado.web.Application([
(r'/index',MainHandle),
(r'/login',LoginHandle),
(r'/test',TestHandle)
],**settings) if __name__ == '__main__':
#创建socket对象,bind.listen
application.listen(8080)
# conn,addr = sock.accept tornado.ioloop.IOLoop.instance().start()

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width">
<title>Title</title>
</head>
<body>
<h4>登录页面</h4>
<form action="" method="post">
{# {{ xsrf_form_html() }}#}
{% raw xsrf_form_html() %} 原生的
用户名:<input type="text" name="user">
密码:<input type="password" name="pwd">
<input type="submit" value="登录">
</form>
</body>
</html>

test.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width">
<title>Title</title>
<link rel="stylesheet" href="/static/test.css"> <!--用之前需要配置一下-->
</head>
<body>
<h1>{{ name }}</h1>
<h2>{{ info.get('age') }}</h2>
<h1>{{ info['name'] }}</h1>
<h1>{{ li }}</h1>
<h1>{{ li[0] }}</h1> ==================循环生成=============
<ul>
{% for i in li%}
<li>{{ i }}</li>
{% end %}
</ul> </body>
</html>

五、自定义session

import tornado.ioloop
import tornado.web #视图
from hashlib import sha1
import os
import time
create_session_id = lambda :sha1(bytes('%s%s'%(os.urandom(16),time.time()),encoding='')).hexdigest()
class SessionSix(object):
session_cache = { #一开是是NOne的 #开辟一个内存空间,保存这个人的状态
# 'sddfgfhsdsffd':{},
# "sdfsdgfgd":{}
} #
def __init__(self,handle):
self.handle = handle
#先获取session_id的值
random_str = self.handle.get_cookie('_session_id')
if not random_str:
#如果没有随机字符串,说明是第一次登陆
random_str = create_session_id()
self.session_cache[random_str] = {}
else:
if random_str not in self.session_cache:#判断他的session_id和自己给它的session_id是否相等
random_str = create_session_id()
self.session_cache[random_str] = {}#你伪造了一个假的,我就认为你是第一次来
self.random_str = random_str #来表示不同的用户对应的身份 def __setitem__(self, key, value):
self.session_cache[self.random_str][key] = value
self.handle.set_cookie('_session_id',create_session_id()) def __getitem__(self, item):
return self.session_cache[self.random_str].get(item) def __delitem__(self, key):
pass
class MainHandle(tornado.web.RequestHandler):
def initialize(self):
self.session = SessionSix(self)
def get(self):
print(self.session['user']) #获取session
# print(self.get_cookie('user'))
self.write('hello world') #默认有个return none
def post(self,*args,**kwargs):
pass class LoginHandle(tornado.web.RequestHandler):
def initialize(self):
# print('123') #在每一次请求开始先执行一下初始化这个方法
self.session = SessionSix(self)
def get(self,*args,**kwargs):
self.render('templates/login.html') #没有脱离文件路径的知识
def post(self,*args,**kwargs):
user = self.get_argument('user')
pwd = self.get_argument('pwd')
print(user,pwd)
if user=='haiyan' and pwd=='':
self.session['user'] = '' #设置自定义的session
# self.set_cookie('user','haiyan',10) #设置cookie,10秒后过期
# self.set_secure_cookie('user','haiyan',) #签名cookie
self.redirect('/index') #要么return一下
else: #要么else分割开,不然会报错
self.render('templates/login.html')
# self.get_arguments() #getlist 像是复选框,一下取多个值 class TestHandle(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
sss = {'name':"haiyan","info":{'name':'小华','age':18},"li":[11,22,33]}
self.render('templates/test.html',**sss) settings={
'static_path':'static',
'xsrf_cookies':True,
'cookie_secret':''
}
#路由分配
application = tornado.web.Application([
(r'/index',MainHandle),
(r'/login',LoginHandle),
(r'/test',TestHandle)
],**settings) if __name__ == '__main__':
#创建socket对象,bind.listen
application.listen(8080)
# conn,addr = sock.accept tornado.ioloop.IOLoop.instance().start()

Tronado的更多相关文章

  1. Tronado自定义Form组件

    Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...

  2. 本博文将一步步带领你实现抽屉官网的各种功能:包括登陆、注册、发送邮箱验证码、登陆验证码、页面登陆验证、发布文章、上传图片、form验证、点赞、评论、文章分页处理以及基于tronado的后端和ajax的前端数据处理。

    本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tronado的后端和ajax的 ...

  3. 初始 Tronado

    安装 pip 安装 pip install tronado 手动安装 下载tronado安装包(https://pypi.python.org/packages/source/t/tornado/to ...

  4. Tronado【第2篇】:tronado自定义Form组件

    Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...

  5. Tronado【第1篇】:tronado的简单使用以及使用

    Tronado Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp ...

  6. tronado学习

    请求处理程序和请求参数: 原创首发:http://www.cnblogs.com/zxlovenet/p/4128644.html 程序将URL映射到tornado.web.RequestHandle ...

  7. Tronado自定义Session

    这里就不一一诉说Session和Cookie直接的关系了,下面以一张图来概括: 下面是一个简单的Tornaod自定义Session的例子,看完后你可能会明白为什么我们在Django里可以直接使用req ...

  8. tornado高效开发必备之源码详解

    前言:本博文重在tornado源码剖析,相信读者读完此文能够更加深入的了解tornado的运行机制,从而更加高效的使用tornado框架. 本文参考武sir博客地址:http://www.cnblog ...

  9. Python介绍

    本节内容 Python简史 Python是一门什么样的语言? Python的优点与缺点 Python解释器 一.Python简史 历史背景 在20世纪80年代,IBM和苹果已经掀起了个人电脑的浪潮.但 ...

随机推荐

  1. shell_mysql_ alias 快速启动

    添加快启动即命令行 ~$ vi .bash_aliases alias mysqlxdb='mysql -uroot -p1 xdb' ~$ source .bashrc 创建脚本xdb.sh#! / ...

  2. 用socket写一个简单的客户端和服务端程序

    用来练手写写socket代码 客户端代码 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h ...

  3. 特征选取1-from sklearn.feature_selection import SelectKBest

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  4. Elasticsearch日志分析系统

    Elasticsearch日志分析系统 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是Elasticsearch 一个采用Restful API标准的高扩展性的和高可用性 ...

  5. strace常用参数详解

    strace常用参数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. strace命令大家应该比我熟悉吧,如果你不知道,呵呵,会可能跟我一样被人说:“我怀疑你是假运维”,不过没关 ...

  6. 基于windows server 2012 的微软桌面虚拟化实战教程

    http://abool.blog.51cto.com/8355508/1587489/ Windows Server2012 中的“远程桌面服务”服务器角色中就提供了允许用户连接到虚拟机.Remot ...

  7. Java Calendar使用总结

    JavaCalendar 类时间操作,这也许是创建和管理日历最简单的一个方案,示范代码很简单. 演示了获取时间,日期时间的累加和累减,以及比较. 原文地址:blog.csdn.NET/joyous/a ...

  8. 2018牛客网暑期ACM多校训练营(第一场)D Two Graphs(图)

    题意 给两个图G1和G2,求G2的子图中与G1同构的数目. 分析 首先n=8,那么n!的算法问题不大.枚举G1的每个点,在G2中找同构的顶点序列.需要注意的是G1存在自同构的情况,所以对G1本身进行一 ...

  9. MyBatis编写映射文件实现增删改操作 附说明及代码

    1.看一下我们接口 package cn.bdqn.mybatis.dao; import org.apache.ibatis.annotations.Select; import cn.bdqn.m ...

  10. JavaScript之表格操作(二)创建表格病填充表格数据

    //创建表格 var tableOptions = { way: "insertBefore", //insertBefore,append positionId: "d ...