玩转PythonWeb框架之Tornado

(1)简介:

Tornado是一种Web服务器软件的开源版本,Tornado是非阻塞式服务器,速度很快。这得益于其非阻塞式和对epoll的运用,Tornado每秒可以处理数以千计的连接,因此Tornado是实时Web服务的一个理想的框架。

Tornado是现在应用最为广泛的Web框架,其具有以下优势:

1.轻量级Web框架

2.异步非阻塞IO处理

3.出色的抗负载能力

4.优秀的处理性能,不依赖多进程和多线程

(2)Tornado与Django的比较:

1.Django是重量级的Web框架,功能齐全,注重开发效率

2.Django内置管理后台

3.Django内置封装完善的ORM操作

4.Django提供Session功能

5.Django与Tornado相比,Django高耦合

6.Tornado与Django相比,入门门槛较高

(3)使用Tornado:

Tornado应该运行在类Unix平台,为了达到最佳的性能和扩展性,仅推荐Linux和BSD(充分利用Linux的epoll工具和BSD的kqueue达到高性能处理的目的

☆安装Tornado:

pip install tornado

☆在代码中导入Tornado:

import tornado.ioloop

import tornado.web

☆Tornado的执行流程:

1.执行Python文件,监听设置的端口

2.浏览器请求服务器,经过路由

3.路由匹配对应的处理器类

4.根据请求类型执行指定处理器类中的处理函数

5.返回处理结果,客户端浏览器渲染页面

创建处理器类,在类中定义HTTP方法:

class MainHandler(tornado.web.RequestHandler):

def get(self):

pass

def post(self):

pass

... # HTTP中的方法

为Tornado设置模板目录:

settings = {

"template_path":"模板路径", # 设置模板目录

}

设置Tornado路由关系:

application = tornado.web.Application([(r"/", MainHandler),], **settings) # 传入设置参数

启动服务:

if __name__ == "__main__":

application.listen(8009) # 设置监听端口

tornado.ioloop.IOLoop.instance().start() # 启动服务

示例代码:

/controller/One.py

import tornado.ioloop

import tornado.web

mylist = []

mylist2 = []

class MainHandler(tornado.web.RequestHandler):

def get(self):

self.render("index.html", list = mylist, list2 = mylist,)

def post(self):

name = self.get_argument("name")

love = self.get_argument("mylove")

mylist.append(name)

mylist2.append(love)

self.render('index.html', list = mylist, list2 = mylist2,)

settings = {

"template_path":"../views", # 设置模板目录

}

application = tornado.web.Application([(r"/index", MainHandler),], **settings) # 传入设置参数

if __name__ == "__main__":

application.listen(8009) # 设置监听端口

tornado.ioloop.IOLoop.instance().start() # 启动服务

/views/index.html

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Index</title>

</head>

<body style="background-color: darkorange;color: aliceblue">

<center>

<h1>Hello,Tornado.</h1>

</center>

<center>

<form action="/index" name="formdata" method="post">

姓名:<input type="text" name="name">

爱好:<select name="mylove" id="">

<option value="movie">电影</option>

<option value="football">足球</option>

<option value="music">音乐</option>

</select>

<input type="submit" value="提交">

<input type="reset" value="重置">

</form>

</center>

<center>

<h2>《提交的信息》</h2>

<h3>

{% for i in list %}

姓名:{{ i }}

{% end %}

{% for x in list2 %}

爱好:{{ x }}

{% end %}

</h3>

</center>

</body>

</html>

(4)路由系统:

Tornado中的URL对应的不是处理函数而是类,在处理类中定义HTTP方法。Tornado中的路由系统可以分为:静态路由、动态路由、请求方法路由、二级路由。

设置路由的时候可以使用URL对应的方式,也可以使用装饰器的方式进行路由映射。

装饰器映射的方式:

@root.route(‘路由URL’)

def MethodHandler(self):

Some...

root.run(host=’IP地址’, port=端口)

☆静态路由:

application = tornado.web.Application([(r"/index/", MainHandler),], **settings)

☆基于正则的动态路由:

application = tornado.web.Application([(r"/index/(\d+)", MainHandler),], **settings)

同时处理器函数也可以传入此参数:

class MainHandler(tornado.web.RequestHandler):

     def get(self,id):         self.render('index.html',id=id)

     def post(self):         pass

使用装饰器操作:

@root.route('/wiki/<pagename>')

def callback(pagename):

...

@root.route('/object/<id:int>')

def callback(id):

...

@root.route('/show/<name:re:[a-z]+>')

def callback(name):

...

@root.route('/static/<path:path>')

def callback(path):

return static_file(path, root='static')

☆请求方法路由:

@root.route('/hello/', method='POST')

# 如果使用@root.get()表示装饰器下的函数只接受get请求

def index():

...

@root.get('/hello/')

def index():

...

@root.post('/hello/')

def index():

...

@root.put('/hello/')

def index():

...

@root.delete('/hello/')

def index():

...

☆二级路由:


主机头


URL正则


Handler


safe


/index/\d*


IndexHandler


/admin/\w*


AdminHandler


/car/\w*


CarHandler


.*


/index/\w*


HomeHandler


/pro/\w*


ProHandler


/.*


AllHandler

application = tornado.web.Application('www.test.com$',[(r"/index/", MainHandler),], **settings)

使用装饰器的方式:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# file:index.py

from bottle import template, Bottle

from bottle import static_file

root = Bottle()

@root.route('/hello/')

def index():

Some...

from framwork_bottle import app01

from framwork_bottle import app02

root.mount('app01', app01.app01)

root.mount('app02', app02.app02)

root.run(host='localhost', port=8888)

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# file:app01.py

from bottle import template, Bottle

app01 = Bottle()

@app01.route('/hello/', method='GET')

def index():

Some...

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# file:app02.py

from bottle import template, Bottle

app02 = Bottle()

@app02.route('/hello/', method='GET')

def index():

Some...

(5)模板引擎:

☆模板语法

<!DOCTYPE html> <html> <head>     <meta charset="UTF-8">     <title>模板引擎语法</title> </head> <body>     <!--单个变量的引用-->     {{ x }}     <!--单行Python代码-->     % temp = "Hello"     <!--多行Python代码-->     <%         Some python codes...     %>     <!--HTML与Python代码混合-->     {% for i in list %}     <h3>{{ i }}</h3>     {% end %}
<!—使用模板自定义编辑块-->
{% block RenderBody %}{% end %}
<!—在其他HTML文件中使用同样的方式在块中间填充数据--> </body> </html>

☆模板函数:

escape: tornado.escape.xhtml_escape 的別名

xhtml_escape: tornado.escape.xhtml_escape 的別名

url_escape: tornado.escape.url_escape 的別名

json_encode: tornado.escape.json_encode 的別名

squeeze: tornado.escape.squeeze 的別名

linkify: tornado.escape.linkify 的別名

datetime: Python 的 datetime 模组

handler: 当前的 RequestHandler 对象

request: handler.request 的別名

current_user: handler.current_user 的別名

locale: handler.locale 的別名

_: handler.locale.translate 的別名

static_url: for handler.static_url 的別名

xsrf_form_html: handler.xsrf_form_html 的別名

☆自定义UIMethod和UIModule:

定义:

# file:uimethods.py

def 自定义函数(self):

Some...

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# uimodules.py

from tornado.web import UIModule

from tornado import escape

class 自定义类(UIModule):

def render(self, *args, **kwargs):

return escape.xhtml_escape('<h1>Test</h1>')

注册:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

# file:test.py

import tornado.ioloop

import tornado.web

from tornado.escape import linkify

import uimodules as md

import uimethods as mt

class MainHandler(tornado.web.RequestHandler):

def get(self):

self.render('index.html')

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()

使用:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title></title>

<link href="{{static_url("commons.css")}}" rel="stylesheet" />

</head>

<body>

<h1>hello</h1>

{% module 自定义类名(123) %}

{{ 自定义函数() }}

</body>

(6)静态缓存:

对于静态文件,可以配置静态文件的目录和前段使用时的前缀,并且Tornaodo还支持静态文件缓存。

配置:

settings = {

'static_url_prefix': '/static/',

}

使用:

<link href="{{static_url("commons.css")}}" rel="stylesheet" />

静态文件缓存的实现:

def get_content_version(cls, abspath):

"""Returns a version string for the resource at the given path.

This class method may be overridden by subclasses.  The

default implementation is a hash of the file's contents.

.. versionadded:: 3.1

"""

data = cls.get_content(abspath)

hasher = hashlib.md5()

if isinstance(data, bytes):

hasher.update(data)

else:

for chunk in data:

hasher.update(chunk)

return hasher.hexdigest()

(7)公共组件:

Web框架的本质就是接受用户请求,处理用户请求,响应请求内容。由开发人员定制用户的请求处理,Web框架接管请求的响应和请求。当接受用户请求的时候会将请求的信息封装在Bottle中的request中,而请求做出响应封装在Bottle的response中,公共组件的本质就是为开发人员提供相关的接口。

request.headers  #请求头信息,可以通过请求头信息来获取相关客户端的信息

request.query #get请求信息,如果用户访问时这样的:http://127.0.0.1:8000/?page=123就必须使用request.query  使用GET方法是无法取到信息的

request.forms #post请求信息

request.files #上传文件信息

request.params #get和post请求信息,他是GET和POST的总和,其实他内部调用了request.get request.forms

request.GET #get请求信息

request.POST #post和上传信息,上传文件信息,和post信息

request.cookies #cookie信息

request.environ #环境相关,如果上面的这些请求信息没有满足需求,就在这里找

(8)XSS跨站脚本攻击与CSRF跨域伪造请求:

XSS:

恶意攻击者往Web页面里插入恶意脚本代码,当用户浏览该页之时,嵌入其中Web里面的脚本代码会被执行,从而达到恶意攻击用户的特殊目的。

CSRF配置:

settings = {

"xsrf_cookies": True,

}

1.  普通的表单使用:

<form action=" " method="post">

{{ xsrf_form_html() }}

Some...

</form>

2.  Ajax使用:

function getCookie(name) {

var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");

return r ? r[1] : undefined;

}

jQuery.postJSON = function(url, args, callback) {

args._xsrf = getCookie("_xsrf");

$.ajax({

url: url,

data: $.param(args),

dataType: "text",

type: "POST",

success: function(response) {

callback(eval("(" + response + ")"));

}});

};

(9)Cookie与Session:

Tornado中可以对cookie进行操作,使用set_cookie(‘ Key’,’Value’)方法进行设置cookie,使用get_cookie(‘Key’)获取Cookie值。

由于Cookie很容易被客户端伪造,假如需要在cookie中保存当前的用户登录状态,需要对cookie进行签名。通过set_secure_cookie(‘Key’,’Value’)和get_secure_cookie(‘Key’)方法设置和使用,但是需要在使用的时候创建一个密钥,叫做cookie_secret。

settings = {

'cookie_secret': '一堆字符串'

}

签名Cookie的本质:

写入cookie的过程:

1.  将值进行base64加密

2.  对除去值以外的内容进行签名,使用无法逆向破解的哈希算法

3.  拼接签名与加密值

读取cookie的过程:

1.  读取加密的内容

2.  对签名进行验证

3.  进行base64解密,获取值的内容

JavaScript操作cookie:

function setCookie(name,value,expires){

var current_date = new Date();

current_date.setSeconds(current_date.getSeconds() + 5);

document.cookie = name + "= "+ value +";expires=" + current_date.toUTCString();

}

自定义Session:

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import tornado.web

import tornado.ioloop

container = {}

class Session:

def __init__(self, handler):

self.handler = handler

self.random_str = None

def __genarate_random_str(self):

import hashlib

import time

obj = hashlib.md5()

obj.update(bytes(str(time.time()), encoding='utf-8'))

random_str = obj.hexdigest()

return random_str

def __setitem__(self, key, value):

# 在container中加入随机字符串

# 定义专属于自己的数据

# 在客户端中写入随机字符串

# 判断,请求的用户是否已有随机字符串

if not self.random_str:

random_str = self.handler.get_cookie('__session__')

if not random_str:

random_str = self.__genarate_random_str()

container[random_str] = {}

else:

# 客户端有随机字符串

if random_str in container.keys():

pass

else:

random_str = self.__genarate_random_str()

container[random_str] = {}

self.random_str = random_str

container[self.random_str][key] = value

self.handler.set_cookie("__session__", self.random_str)

def __getitem__(self, key):

# 获取客户端的随机字符串

# 从container中获取专属于我的数据

# 专属信息【key】

random_str =  self.handler.get_cookie("__session__")

if not random_str:

return None

# 客户端有随机字符串

user_info_dict = container.get(random_str,None)

if not user_info_dict:

return None

value = user_info_dict.get(key, None)

return value

class BaseHandler(tornado.web.RequestHandler):

def initialize(self):

self.session = Session(self)

一致性哈希:

#!/usr/bin/env python

#coding:utf-8

import sys

import math

from bisect import bisect

if sys.version_info >= (2, 5):

import hashlib

md5_constructor = hashlib.md5

else:

import md5

md5_constructor = md5.new

class HashRing(object):

"""一致性哈希"""

def __init__(self,nodes):

'''初始化

nodes : 初始化的节点,其中包含节点已经节点对应的权重

默认每一个节点有32个虚拟节点

对于权重,通过多创建虚拟节点来实现

如:nodes = [

{'host':'127.0.0.1:8000','weight':1},

{'host':'127.0.0.1:8001','weight':2},

{'host':'127.0.0.1:8002','weight':1},

]

'''

self.ring = dict()

self._sorted_keys = []

self.total_weight = 0

self.__generate_circle(nodes)

def __generate_circle(self,nodes):

for node_info in nodes:

self.total_weight += node_info.get('weight',1)

for node_info in nodes:

weight = node_info.get('weight',1)

node = node_info.get('host',None)

virtual_node_count = math.floor((32*len(nodes)*weight) / self.total_weight)

for i in xrange(0,int(virtual_node_count)):

key = self.gen_key_thirty_two( '%s-%s' % (node, i) )

if self._sorted_keys.__contains__(key):

raise Exception('该节点已经存在.')

self.ring[key] = node

self._sorted_keys.append(key)

def add_node(self,node):

''' 新建节点

node : 要添加的节点,格式为:{'host':'127.0.0.1:8002','weight':1},其中第一个元素表示节点,第二个元素表示该节点的权重。

'''

node = node.get('host',None)

if not node:

raise Exception('节点的地址不能为空.')

weight = node.get('weight',1)

self.total_weight += weight

nodes_count = len(self._sorted_keys) + 1

virtual_node_count = math.floor((32 * nodes_count * weight) / self.total_weight)

for i in xrange(0,int(virtual_node_count)):

key = self.gen_key_thirty_two( '%s-%s' % (node, i) )

if self._sorted_keys.__contains__(key):

raise Exception('该节点已经存在.')

self.ring[key] = node

self._sorted_keys.append(key)

def remove_node(self,node):

''' 移除节点

node : 要移除的节点 '127.0.0.1:8000'

'''

for key,value in self.ring.items():

if value == node:

del self.ring[key]

self._sorted_keys.remove(key)

def get_node(self,string_key):

'''获取 string_key 所在的节点'''

pos = self.get_node_pos(string_key)

if pos is None:

return None

return self.ring[ self._sorted_keys[pos]].split(':')

def get_node_pos(self,string_key):

'''获取 string_key 所在的节点的索引'''

if not self.ring:

return None

key = self.gen_key_thirty_two(string_key)

nodes = self._sorted_keys

pos = bisect(nodes, key)

return pos

def gen_key_thirty_two(self, key):

m = md5_constructor()

m.update(key)

return long(m.hexdigest(), 16)

def gen_key_sixteen(self,key):

b_key = self.__hash_digest(key)

return self.__hash_val(b_key, lambda x: x)

def __hash_val(self, b_key, entry_fn):

return (( b_key[entry_fn(3)] << 24)|(b_key[entry_fn(2)] << 16)|(b_key[entry_fn(1)] << 8)| b_key[entry_fn(0)] )

def __hash_digest(self, key):

m = md5_constructor()

m.update(key)

return map(ord, m.digest())

"""

nodes = [

{'host':'127.0.0.1:8000','weight':1},

{'host':'127.0.0.1:8001','weight':2},

{'host':'127.0.0.1:8002','weight':1},

]

ring = HashRing(nodes)

result = ring.get_node('98708798709870987098709879087')

print result

"""

自定义Session:

from hashlib import sha1

import os, time

create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest()

class Session(object):

session_id = "__sessionId__"

def __init__(self, request):

session_value = request.get_cookie(Session.session_id)

if not session_value:

self._id = create_session_id()

else:

self._id = session_value

request.set_cookie(Session.session_id, self._id)

def __getitem__(self, key):

# 根据 self._id ,在一致性哈希中找到其对应的服务器IP

# 找到相对应的redis服务器,如: r = redis.StrictRedis(host='localhost', port=6379, db=0)

# 使用python redis api 链接

# 获取数据,即:

# return self._redis.hget(self._id, name)

def __setitem__(self, key, value):

# 根据 self._id ,在一致性哈希中找到其对应的服务器IP

# 使用python redis api 链接

# 设置session

# self._redis.hset(self._id, name, value)

def __delitem__(self, key):

# 根据 self._id 找到相对应的redis服务器

# 使用python redis api 链接

# 删除,即:

return self._redis.hdel(self._id, name)

(10)文件上传:

使用Form表单:

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

<title>上传文件</title>

</head>

<body>

<form id="my_form" name="form" action="/index" method="POST"  enctype="multipart/form-data" >

<input name="fff" id="my_file"  type="file" />

<input type="submit" value="提交"  />

</form>

</body>

</html>

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import tornado.ioloop

import tornado.web

class MainHandler(tornado.web.RequestHandler):

def get(self):

self.render('index.html')

def post(self, *args, **kwargs):

file_metas = self.request.files["fff"]

# print(file_metas)

for meta in file_metas:

file_name = meta['filename']

with open(file_name,'wb') as up:

up.write(meta['body'])

settings = {

'template_path': 'template',

}

application = tornado.web.Application([

(r"/index", MainHandler),

], **settings)

if __name__ == "__main__":

application.listen(8000)

tornado.ioloop.IOLoop.instance().start()

使用AjaxXMLHttpRequest:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title></title>

</head>

<body>

<input type="file" id="img" />

<input type="button" onclick="UploadFile();" />

<script>

function UploadFile(){

var fileObj = document.getElementById("img").files[0];

var form = new FormData();

form.append("fff", fileObj);

var xhr = new XMLHttpRequest();

xhr.open("post", '/index', true);

xhr.send(form);

}

</script>

</body>

</html>

使用Ajax-jQuery:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title></title>

</head>

<body>

<input type="file" id="img" />

<input type="button" onclick="UploadFile();" />

<script>

function UploadFile(){

var fileObj = $("#img")[0].files[0];

var form = new FormData();

form.append("fff", fileObj);

$.ajax({

type:'POST',

url: '/index',

data: form,

processData: false,  // tell jQuery not to process the data

contentType: false,  // tell jQuery not to set contentType

success: function(arg){

console.log(arg);

}

})

}

</script>

</body>

</html>

使用iframe预览图片:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title></title>

</head>

<body>

<form id="my_form" name="form" action="/index" method="POST"  enctype="multipart/form-data" >

<div id="main">

<input name="fff" id="my_file"  type="file" />

<input type="button" name="action" value="Upload" onclick="redirect()"/>

<iframe id='my_iframe' name='my_iframe' src="" ></iframe>

</div>

</form>

<script>

function redirect(){

document.getElementById('my_iframe').onload = Testt;

document.getElementById('my_form').target = 'my_iframe';

document.getElementById('my_form').submit();

}

function Testt(ths){

var t = $("#my_iframe").contents().find("body").text();

console.log(t);

}

</script>

</body>

</html>

原文地址:http://blog.51cto.com/xvjunjie/2072332

时间: 2024-10-13 10:45:58

玩转PythonWeb框架之Tornado的相关文章

Python-----Web框架之Tornado

Python-----Web框架之Tornado 概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化. Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快.得利于其 非阻塞的方式和对 

PythonWEB框架之Tornado

前言 Tornado(龙卷风)和Django一样是Python中比较主流的web框架,Tornado 和现在的主流 Web 服务器框架也有着明显的区别:Tornado自带socket,并且实现了异步非阻塞并对WebSocket协议天然支持: 一.Tornado框架的基本组成 Tonado由 路由系统.视图.模板语言4大部分组成,如果习惯了使用Django你会感觉它功能单薄,但是只有这样才能足够轻量,如果用到什么功能就自己去GitHub上找现成的插件,或者自实现:以下将对这些基本组件进行逐一介绍.

Python框架之Tornado(一)

本系列博文计划: 1.剖析基于Python的Web框架Tornado的源码 2.为Python开发一个完善的MVC框架 首先将带着大家一起来剖析基于python编写的Web框架 tornado ,本着易读易懂的目标来写这一系列,寄希让小白也能zeng明白其中的道理,与其说剖析还不如说是白话,因为本系列都会用通俗的语言去描述Web框架中的各个知识点. 一个脚本引发的一场“案例”.... 运行脚本并在浏览器上访问http://127.0.0.1:8080 #!/usr/bin/env python

框架之Tornado(简单介绍)

引言 回想Django的部署方式 以Django为代表的python web应用部署时采用wsgi协议与服务器对接(被服务器托管),而这类服务器通常都是基于多线程的,也就是说每一个网络请求服务器都会有一个对应的线程来用web应用(如Django)进行处理. 考虑两类应用场景 用户量大,高并发 如秒杀抢购.双十一某宝购物.春节抢火车票 大量的HTTP持久连接 使用同一个TCP连接来发送和接收多个HTTP请求/应答,而不是为每一个新的请求/应答打开新的连接的方法. 对于HTTP 1.0,可以在请求的

pythonWeb框架flask中使用blinker信号机制解耦业务代码解决ImportError: cannot import name &#39;app&#39;,以异步发送邮件为例

百度了大半天,不知道怎么搞,直到学习了blinker才想到解决办法,因为之前写java都是文件分开的, 所以发送邮件业务代码也放到view里面,但是异步线程需要使用app,蛋疼的是其他模块不能从app.py导入任何变量: 即: app.py是主文件,view.py是业务文件, 我需要在view中使用app中的变量,怎么办,百度了很多,没有找到方法 这里可以用信号实现,先记录一下: python3内置了blinker,可以直接使用,首先在view里定义信号: 然后在app.py里面连接需要使用的函

web框架之Tornado

Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本. 这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化. Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快. 得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以

Python框架之Tornado(四)源码之褪去模板外衣的前戏

执行字符串表示的函数,并为该函数提供全局变量 本篇的内容从题目中就可以看出来,就是为之后剖析tornado模板做准备,也是由于该知识点使用的巧妙,所有就单独用一篇来介绍了.废话不多说,直接上代码: #!usr/bin/env python #coding:utf-8 namespace = {'name':'xs','data':[18,73,84]} code = '''def hellocute():return "name %s ,age %d" %(name,data[0],)

Python框架之Tornado(四)源码之褪去模板外衣

上一篇介绍了客户端请求在tornado框架中的生命周期,其本质就是利用epoll和socket来获取并处理请求.在上一篇的内容中,我们只是给客户端返回了简单的字符串,如:“Hello World”,而在实际开发中,需要使用html文件的内容作为模板,然后将被处理后的数据(计算或数据库中的数据)嵌套在模板中,然后将嵌套了数据的html文件的内容返回给请求者客户端,本篇就来详细的剖析模板处理的整个过程. 概述 上图是返回给用户一个html文件的整个流程,较之前的Demo多了绿色流线的步骤,其实就是把

Python开发【第十五篇】:Web框架之Tornado

概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化. Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快.得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数