Tronado

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 ...)的不同调用并执行相应的方法

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

1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 #!/usr/bin/env python
4 # -*- coding:utf-8 -*-
5
6 import tornado.ioloop
7 import tornado.web
8 from tornado import httpclient
9 from tornado.web import asynchronous
10 from tornado import gen
11
12 import uimodules as md
13 import uimethods as mt
14
15 class MainHandler(tornado.web.RequestHandler):
16 @asynchronous
17 @gen.coroutine
18 def get(self):
19 print 'start get '
20 http = httpclient.AsyncHTTPClient()
21 http.fetch("http://127.0.0.1:8008/post/", self.callback)
22 self.write('end')
23
24 def callback(self, response):
25 print response.body
26
27 settings = {
28 'template_path': 'template',
29 'static_path': 'static',
30 'static_url_prefix': '/static/',
31 'ui_methods': mt,
32 'ui_modules': md,
33 }
34
35 application = tornado.web.Application([
36 (r"/index", MainHandler),
37 ], **settings)
38
39
40 if __name__ == "__main__":
41 application.listen(8009)
42 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 模块 的代码文档中有着详细的描述

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
5 <title>老男孩</title>
6 <link href="{{static_url("css/common.css")}}" rel="stylesheet" />
7 {% block CSS %}{% end %}
8 </head>
9 <body>
10
11 <div class="pg-header">
12
13 </div>
14
15 {% block RenderBody %}{% end %}
16
17 <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script>
18
19 {% block JavaScript %}{% end %}
20 </body>
21 </html>

layout

1 {% extends 'layout.html'%}
2 {% block CSS %}
3 <link href="{{static_url("css/index.css")}}" rel="stylesheet" />
4 {% end %}
5
6 {% block RenderBody %}
7 <h1>Index</h1>
8
9 <ul>
10 {% for item in li %}
11 <li>{{item}}</li>
12 {% end %}
13 </ul>
14
15 {% end %}
16
17 {% block JavaScript %}
18
19 {% 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('123') #在每一次请求开始先执行一下初始化这个方法
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=='123':
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':'1254'
}
#路由分配
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=='123':
self.session['user'] = '666' #设置自定义的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':'1254'
}
#路由分配
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的简单使用以及使用的更多相关文章

  1. iOS开发UI篇—xib的简单使用

    iOS开发UI篇—xib的简单使用 一.简单介绍 xib和storyboard的比较,一个轻量级一个重量级. 共同点: 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: ...

  2. Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码

    Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本文主要是记录一写我在学习MapReduce时的一些 ...

  3. rabbitMQ第二篇:java简单的实现RabbitMQ

    前言:在这里我将用java来简单的实现rabbitMQ.下面我们带着下面问题来一步步的了解和学习rabbitMQ. 1:如果消费者连接中断,这期间我们应该怎么办 2:如何做到负载均衡 3:如何有效的将 ...

  4. gradle教程 [原创](eclipse/ADT下 非插件 非Android Studio/AS)纯手打 第二篇:gradle简单实战

    一个bug 一个脚印的叫你们用gradle. 1介于网络上的很多资料都是老的 不适用与现在的新版本gradle 尤其是有些gradle方法改名了老的用不了 2介于网上都是粘贴复制并且零碎我很蛋疼啊,走 ...

  5. Golang学习-第二篇 搭建一个简单的Go Web服务器

    序言 由于本人一直从事Web服务器端的程序开发,所以在学习Golang也想从Web这里开始学起,如果对Golang还不太清楚怎么搭建环境的朋友们可以参考我的上一篇文章 Golang的简单介绍及Wind ...

  6. iOS开发多线程篇 09 —NSOperation简单介绍

    iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...

  7. Android系统篇之—-编写简单的驱动程序并且将其编译到内核源码中【转】

    本文转载自:大神 通过之前的一篇文章,我们了解了 Android中的Binder机制和远程服务调用 在这篇文章中主要介绍了Android中的应用在调用一些系统服务的时候的原理,那么接下来就继续来介绍一 ...

  8. Win32编程API 基础篇 -- 2.一个简单的窗口 根据英文教程翻译

    一个简单的窗口 例子:简单的窗口 有时人们在IRC提问,”我应该怎样制作一个窗口”...嗯,这恐怕不是完全这么简单好回答!其实这并不难一旦你明白你在做什么,但在你得到一个可展示的窗口之前还有一些事情需 ...

  9. 转一篇关于vuex简单理解的文章

    学习vuex半天摸不着头脑无意间发现了这篇文章 对vuex做了一个简单的阐述比较有助于我的理解 现在分享出来希望能给一些朋友一点帮助  这个是原文地址 http://www.ituring.com.c ...

  10. 第二篇:docker 简单入门(二)

    本篇目录 写在最前面的话 最常用的docker命令 获取远程仓库镜像 写在最前面的话 如上图大家看到的这样,以后此类文章请到其他平台查阅,由于博客园提示说,内容太多简单,所以以后简单的内容我会放在cs ...

随机推荐

  1. WebLogic下Argument(s) "type" can't be null.

    启动项目出现Argument(s) "type" can't be null.异常.异常如下: java.lang.IllegalArgumentException: Argume ...

  2. python__007内置函数

    本文摘自:https://docs.python.org/3/library/functions.html?highlight=built#ascii     内置功能     abs() delat ...

  3. LeetCode.977-排序数组的平方(Squares of a Sorted Array)

    这是悦乐书的第369次更新,第397篇原创 01看题和准备 今天介绍的是LeetCode算法题中Easy级别的第231题(顺位题号是977).给定一个整数数组A按有序递增顺序排序,返回每个数字的平方, ...

  4. 基于LVM(逻辑卷管理)的快照原理

    一.为甚么不管多大的逻辑卷进行备份,快照都会在几秒之内完成? 快照在拍摄的一瞬间,系统会记录那个时间点逻辑卷的状态.数据等,此时拍下的快照相当于一张白纸.如图所示 快照做好后,随着时间的推移,源卷里的 ...

  5. HTML协义代码

    这些状态码被分为五大类: 100-199 用于指定客户端应相应的某些动作. 200-299 用于表示请求成功. 300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息. 400- ...

  6. ros3。3教程 入门到高级

    115.com 目录route 基 础 篇(21课) 1 Ros简介 主要讲解ros的基础知识,让用户对ros有个大致了解,并对ros进行简单演示 语音视频 20分16秒   2 CDROM安装 主要 ...

  7. IntelliJ IDEA将导入的项目转成maven项目

    今天导入公司的maven项目,发现结构不对劲,难怪说为啥一直不能部署tomcat,后面百度才了解到导入这个项目还不是maven项目,首先需要把这个项目变成maven项目,然后再进行tomcat的部署下 ...

  8. [ASP.NET] [JS] GridView点击高亮当前选择行,并在点击另一行时恢复上一选择行背景颜色

    在ASP.NET中的gridview控件里面可以通过设定其OnRowDataBound事件来进行实现高亮当前行的操作 前端控件的设置: 只要设置好OnRowDataBound属性即可,会自动在.cs文 ...

  9. python 并发编程 协程池

    协程池 from gevent.pool import Pool from gevent import monkey;monkey.patch_all() import gevent from gev ...

  10. Linux 下文件句柄数的查询学习

    1. 查看 所有进程的 打开的句柄数 lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more 效果为: 2. 查看某一个进程内的 文件信息 lsof ...