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. VirtualBox上Centos7磁盘扩容

    VirtualBox上Centos7磁盘扩容 非常实用 点击直达

  2. JavaScript日常学习6

    JavaScript的运算符.比较符.条件语句.循环语句.跳出循环(break.continue).标签 JavaScript的运算符.比较符.条件语句.循环语句.跳出循环(break.continu ...

  3. 阶段3 2.Spring_10.Spring中事务控制_7 spring基于注解的声明式事务控制

    创建新项目 复制上一个pom.xml的内容.依赖和打包的方式 再复制src的代码过来 bean.xml.多导入context的声明 Service的实现类增加注解 dao的set方法删掉 通过Auto ...

  4. 在线运行.NET代码

    https://dotnetfiddle.net/ https://try.dot.net/ C# 发送Http协议 模拟 Post Get请求 1.参数 paramsValue的格式 要和 Requ ...

  5. vim开发配置

    需求:使用vim开发python,可以进行简单配置 cd 到用户宿主目录下 vim .vimrc 粘贴以下内容: 版本一: set encoding=utf-8"去掉vi的一致性" ...

  6. python学习之模块-模块(四)

    5.9 logging模块 常用参数 logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有: filename:用指定的文件名创建FiledHan ...

  7. LeetCode.927-独特邮箱地址(Unique Email Addresses)

    这是悦乐书的第356次更新,第383篇原创 01看题和准备 今天介绍的是LeetCode算法题中Easy级别的第218题(顺位题号是927).每封电子邮件都包含本地名称和域名,以@符号分隔. 例如,在 ...

  8. ubuntu分区建议总结

    本文为转载别人的内容,结合了其他内容,进行分区的总结.其中主要是分区表格,对于ubuntu安装时,进行分区非常有用. 无论是安装Windows还是Linux操作系统,硬盘分区都是整个系统安装过程中最为 ...

  9. 第七周课程总结&实验报告

    课程总结 主要学习了抽象类与接口的应用 1.抽象类的成员可以具有访问级别 接口的成员全部public级别 2.抽象类可以包含字段 接口不可以 3.抽象类可以继承接口 接口不能继承抽象类 4.抽象类的成 ...

  10. hive排错

    找出错的那个hive实例,看错误日志: 点下面stdout,找Error