天天看點

python-tornado操作

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      

基本使用

# -*- coding:utf-8 -*-
  
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 ...)的不同調用并執行相應的方法

第五步:方法傳回值的字元串内容發送浏覽器      
# -*- 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對應的是一個類。      
# -*- coding:utf-8 -*-
  
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 語句的格式基本完全相同。我們支援 if、for、while 和 try,這些語句邏輯結束的位置需要用 {% end %} 做标記。還通過 extends 和 block 語句實作了模闆繼承。      
<!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>      
{% 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 %}      
# -*- coding:utf-8 -*-
  
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()      
在模闆中預設提供了一些函數、字段、類以供模闆使用:

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 的別名      

四、實用功能

1、靜态檔案

對于靜态檔案,可以配置靜态檔案的目錄和前段使用時的字首,并且Tornaodo還支援靜态檔案緩存。

# -*- coding:utf-8 -*-
 
import tornado.ioloop
import tornado.web
 
 
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('home/index.html')
 
settings = {
    'template_path': 'template',
    'static_path': 'static',
    'static_url_prefix': '/static/',
}
 
application = tornado.web.Application([
    (r"/index", MainHandler),
], **settings)
 
 
if __name__ == "__main__":
    application.listen(80)
    tornado.ioloop.IOLoop.instance().start()      
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
    <h1>hello</h1>
</body>
</html>      

2、csrf

Tornado中的誇張請求僞造和Django中的相似,跨站僞造請求(Cross-site request forgery)

settings = {
    "xsrf_cookies": True,
}
application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/login", LoginHandler),
], **settings)      
<form action="/new_message" method="post">
  {{ xsrf_form_html() }}
  <input type="text" name="message"/>
  <input type="submit" value="Post"/>
</form>      
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 + ")"));
    }});
};      

注:Ajax使用時,本質上就是去擷取本地的cookie,攜帶cookie再來發送請求

3、cookie

Tornado中可以對cookie進行操作,并且還可以對cookie進行簽名以放置僞造。

繼續閱讀