Tornado

来源:https://www.cnblogs.com/JcrLive/archive/2020/03/03/12404972.html
-Advertisement-
Play Games

Tornado 是 FriendFeed 使用的可擴展的非阻塞式 web 伺服器及其相關工具的開源版本。這個 Web 框架看起來有些像web.py 或者 Google 的 webapp,不過為了能有效利用非阻塞式伺服器環境,這個 Web 框架還包含了一些相關的有用工具 和優化。 Tornado 和現 ...


Tornado 是 FriendFeed 使用的可擴展的非阻塞式 web 伺服器及其相關工具的開源版本。這個 Web 框架看起來有些像web.py 或者 Google 的 webapp,不過為了能有效利用非阻塞式伺服器環境,這個 Web 框架還包含了一些相關的有用工具 和優化。

Tornado 和現在的主流 Web 伺服器框架(包括大多數 Python 的框架)有著明顯的區別:它是非阻塞式伺服器,而且速度相當快。得利於其 非阻塞的方式和對 epoll 的運用,Tornado 每秒可以處理數以千計的連接,這意味著對於實時 Web 服務來說,Tornado 是一個理想的 Web 框架。我們開發這個 Web 伺服器的主要目的就是為了處理 FriendFeed 的實時功能 ——在 FriendFeed 的應用里每一個活動用戶都會保持著一個伺服器連接。(關於如何擴容 伺服器,以處理數以千計的客戶端的連接的問題,請參閱 C10K problem。)

 

 

pip install tornado

源碼安裝     https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz     一、快速上手  

第一步:執行腳本,監聽xxxx埠

第二步:瀏覽器客戶端訪問 /index  -->  http://127.0.0.1:xxxx/index

第三步:伺服器接受請求,並交由對應的類處理該請求

第四步:類接受到請求之後,根據請求方式(post / get / delete ...)的不同調用並執行相應的方法

第五步:方法返回值的字元串內容發送瀏覽器

 

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3   
 4 import tornado.ioloop
 5 import tornado.web
 6   
 7   
 8 class MainHandler(tornado.web.RequestHandler):
 9     def get(self):
10         self.write("Hello, world")
11   
12 application = tornado.web.Application([
13     ("/index", MainHandler),
14 ])
15   
16   
17 if __name__ == "__main__":
18     application.listen(xxxx埠號)
19     tornado.ioloop.IOLoop.instance().start()
View Code
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import tornado.ioloop
 5 import tornado.web
 6 from tornado import httpclient
 7 from tornado.web import asynchronous
 8 from tornado import gen
 9 
10 import uimodules as md
11 import uimethods as mt
12 
13 class MainHandler(tornado.web.RequestHandler):
14         @asynchronous
15         @gen.coroutine
16         def get(self):
17             print 'start get '
18             http = httpclient.AsyncHTTPClient()
19             http.fetch("http://127.0.0.1:8008/post/", self.callback)
20             self.write('end')
21 
22         def callback(self, response):
23             print response.body
24 
25 settings = {
26     'template_path': 'template',
27     'static_path': 'static',
28     'static_url_prefix': '/static/',
29     'ui_methods': mt,
30     'ui_modules': md,
31 }
32 
33 application = tornado.web.Application([
34     (r"/index", MainHandler),
35 ], **settings)
36 
37 
38 if __name__ == "__main__":
39     application.listen(8009)
40     tornado.ioloop.IOLoop.instance().start()
非同步非阻塞例子

二、路由系統

路由系統其實就是 url 和 類 的對應關係,這裡不同於其他框架,其他很多框架均是 url 對應 函數,Tornado中每個url對應的是一個類。

 

 1 #!/usr/bin/env python
 2  2 # -*- coding:utf-8 -*-
 3  3   
 4  4 import tornado.ioloop
 5  5 import tornado.web
 6  6   
 7  7   
 8  8 class MainHandler(tornado.web.RequestHandler):
 9  9     def get(self):
10 10         self.write("Hello, world")
11 11   
12 12 class StoryHandler(tornado.web.RequestHandler):
13 13     def get(self, story_id):
14 14         self.write("You requested the story " + story_id)
15 15   
16 16 class BuyHandler(tornado.web.RequestHandler):
17 17     def get(self):
18 18         self.write("buy.xxx.com/index")
19 19   
20 20 application = tornado.web.Application([
21 21     ("/index", MainHandler),
22 22     ("/story/([0-9]+)", StoryHandler),
23 23 ])
24 24   
25 25 application.add_handlers('buy.xxx.com$', [
26 26     ('/index',BuyHandler),
27 27 ])
28 28   
29 29 if __name__ == "__main__":
30 30     application.listen(80)
31 31     tornado.ioloop.IOLoop.instance().start()
View Code

 

三、模板

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     <link href="{{static_url("css/common.css")}}" rel="stylesheet" />
 6     {% block CSS %}{% end %}
 7 </head>
 8 <body>
 9 
10     <div class="pg-header">
11 
12     </div>
13     
14     {% block RenderBody %}{% end %}
15    
16     <script src="{{static_url("js/jquery-3.4.1.js")}}"></script>
17     
18     {% block JavaScript %}{% end %}
19 </body>
20 </html>
layout.html
 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.html
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3   
 4 import tornado.ioloop
 5 import tornado.web
 6   
 7   
 8 class MainHandler(tornado.web.RequestHandler):
 9     def get(self):
10         self.render('home/index.html')
11   
12 settings = {
13     'template_path': 'template',
14 }
15   
16 application = tornado.web.Application([
17     (r"/index", MainHandler),
18 ], **settings)
19   
20   
21 if __name__ == "__main__":
22     application.listen(80)
23     tornado.ioloop.IOLoop.instance().start()
xxx.py

在模板中預設提供了一些函數、欄位、類以供模板使用:

  • escapetornado.escape.xhtml_escape 的別名
  • xhtml_escapetornado.escape.xhtml_escape 的別名
  • url_escapetornado.escape.url_escape 的別名
  • json_encodetornado.escape.json_encode 的別名
  • squeezetornado.escape.squeeze 的別名
  • linkifytornado.escape.linkify 的別名
  • datetime: Python 的 datetime 模組
  • handler: 當前的 RequestHandler 對象
  • requesthandler.request 的別名
  • current_userhandler.current_user 的別名
  • localehandler.locale 的別名
  • _handler.locale.translate 的別名
  • static_url: for handler.static_url 的別名
  • xsrf_form_htmlhandler.xsrf_form_html 的別名

Tornado預設提供的這些功能其實本質上就是 UIMethod 和 UIModule,我們也可以自定義從而實現類似於Django的simple_tag的功能

1、定義

1 # uimethods.py
2  
3 def tab(self):
4     return 'UIMethod'
uimethods.py
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from tornado.web import UIModule
 4 from tornado import escape
 5 
 6 class custom(UIModule):
 7 
 8     def render(self, *args, **kwargs):
 9         return escape.xhtml_escape('<h1>xxx</h1>')
10         #return escape.xhtml_escape('<h1>xxx</h1>')
uimodules.py

2、註冊

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import tornado.ioloop
 5 import tornado.web
 6 from tornado.escape import linkify
 7 import uimodules as md
 8 import uimethods as mt
 9 
10 class MainHandler(tornado.web.RequestHandler):
11     def get(self):
12         self.render('index.html')
13 
14 settings = {
15     'template_path': 'template',
16     'static_path': 'static',
17     'static_url_prefix': '/static/',
18     'ui_methods': mt,
19     'ui_modules': md,
20 }
21 
22 application = tornado.web.Application([
23     (r"/index", MainHandler),
24 ], **settings)
25 
26 
27 if __name__ == "__main__":
28     application.listen(8009)
29     tornado.ioloop.IOLoop.instance().start()
main.py

3、使用

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6     <link href="{{static_url("commons.css")}}" rel="stylesheet" />
 7 </head>
 8 <body>
 9     <h1>hello</h1>
10     {% module custom(123) %}
11     {{ tab() }}
12 </body>
index.html

四、實用功能

1、靜態文件

對於靜態文件,可以配置靜態文件的目錄和前段使用時的首碼,並且Tornaodo還支持靜態文件緩存。

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3  
 4 import tornado.ioloop
 5 import tornado.web
 6  
 7  
 8 class MainHandler(tornado.web.RequestHandler):
 9     def get(self):
10         self.render('home/index.html')
11  
12 settings = {
13     'template_path': 'template',
14     'static_path': 'static',
15     'static_url_prefix': '/static/',
16 }
17  
18 application = tornado.web.Application([
19     (r"/index", MainHandler),
20 ], **settings)
21  
22  
23 if __name__ == "__main__":
24     application.listen(80)
25     tornado.ioloop.IOLoop.instance().start()
main.py
 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title></title>
 6     <link href="{{static_url("commons.css")}}" rel="stylesheet" />
 7 </head>
 8 <body>
 9     <h1>hello</h1>
10 </body>
11 </html>
index.html
 1     def get_content_version(cls, abspath):
 2         """Returns a version string for the resource at the given path.
 3 
 4         This class method may be overridden by subclasses.  The
 5         default implementation is a hash of the file's contents.
 6 
 7         .. versionadded:: 3.1
 8         """
 9         data = cls.get_content(abspath)
10         hasher = hashlib.md5()
11         if isinstance(data, bytes):
12             hasher.update(data)
13         else:
14             for chunk in data:
15                 hasher.update(chunk)
16         return hasher.hexdigest()
靜態文件緩存的實現

2、csrf

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

1 settings = {
2     "xsrf_cookies": True,
3 }
4 application = tornado.web.Application([
5     (r"/", MainHandler),
6     (r"/login", LoginHandler),
7 ], **settings)
配置
1 <form action="/new_message" method="post">
2   {{ xsrf_form_html() }}
3   <input type="text" name="message"/>
4   <input type="submit" value="Post"/>
5 </form>
普通表單
 1 function getCookie(name) {
 2     var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
 3     return r ? r[1] : undefined;
 4 }
 5 
 6 jQuery.postJSON = function(url, args, callback) {
 7     args._xsrf = getCookie("_xsrf");
 8     $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
 9         success: function(response) {
10         callback(eval("(" + response + ")"));
11     }});
12 };
Ajax 使用時,本質上就是去獲取本地的cookie,攜帶cookie再來發送請求

3、cookie

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

1 class MainHandler(tornado.web.RequestHandler):
2     def get(self):
3         if not self.get_cookie("mycookie"):
4             self.set_cookie("mycookie", "myvalue")
5             self.write("Your cookie was not set yet!")
6         else:
7             self.write("Your cookie was set!")
基本使用

簽名

Cookie 很容易被惡意的客戶端偽造。加入你想在 cookie 中保存當前登陸用戶的 id 之類的信息,你需要對 cookie 作簽名以防止偽造。Tornado 通過 set_secure_cookie 和 get_secure_cookie 方法直接支持了這種功能。 要使用這些方法,你需要在創建應用時提供一個密鑰,名字為 cookie_secret。 你可以把它作為一個關鍵詞參數傳入應用的設置中

 1 class MainHandler(tornado.web.RequestHandler):
 2     def get(self):
 3         if not self.get_secure_cookie("mycookie"):
 4             self.set_secure_cookie("mycookie", "myvalue")
 5             self.write("Your cookie was not set yet!")
 6         else:
 7             self.write("Your cookie was set!")
 8              
 9 application = tornado.web.Application([
10     (r"/", MainHandler),
11 ], cookie_secret="61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=")
View Code
 1 def _create_signature_v1(secret, *parts):
 2     hash = hmac.new(utf8(secret), digestmod=hashlib.sha1)
 3     for part in parts:
 4         hash.update(utf8(part))
 5     return utf8(hash.hexdigest())
 6 
 7 
 8 def _create_signature_v2(secret, s):
 9     hash = hmac.new(utf8(secret), digestmod=hashlib.sha256)
10     hash.update(utf8(s))
11     return utf8(hash.hexdigest())
內部演算法
 1 def create_signed_value(secret, name, value, version=None, clock=None,
 2                         key_version=None):
 3     if version is None:
 4         version = DEFAULT_SIGNED_VALUE_VERSION
 5     if clock is None:
 6         clock = time.time
 7 
 8     timestamp = utf8(str(int(clock())))
 9     value = base64.b64encode(utf8(value))
10     if version == 1:
11         signature = _create_signature_v1(secret, name, value, timestamp)
12         value = b"|".join([value, timestamp, signature])
13         return value
14     elif version == 2:
15         # The v2 format consists of a 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、vue-cli 4.0 中打包後,頁面空白,路徑錯誤。 https://blog.csdn.net/qq_40999917/article/details/102954245 2、vue2修改瀏覽器顯示title。 https://segmentfault.com/a/1190000020208 ...
  • 今天遇到一個很狗血的問題,ie8以下瀏覽器jquery控制台會報錯,原因是jquery2.0以上的版本不支持addEventListener屬性或方法。更換了jquery的版本後問題解決了,happy! ...
  • 近日,微軟發佈了.NET Core 2.0,但是開發人員中間仍然存在一些疑惑,就是.NET Core、.NET Standard、Xamarin和.NET Framework有什麼不同。 .NET Framework用於構建桌面應用程式和運行在互聯網信息伺服器(IIS)上的ASP.NET應用程式。它 ...
  • 選擇題 題目1(單選): 下列選項中定義變數哪一項是正確的(D ) 選項: A.byte b=128; B.long c=3.14L; C.float f=3.14; D.double e=4.88; 題目2(單選): 關於變數的定義,下列寫法正確的是( A ) 選項: A. byte b = 10 ...
  • 選題題 題目1(單選): 下麵有關Java語言跨平臺性說法正確的是(D ) 選項 : A.Java的源代碼是跨平臺的。 B.JDK是跨平臺的。 C.JVM是跨平臺的。 D.跨平臺中的平臺指的是操作系統,Java語言的跨平臺性是指Java程式可以在不同的操作系統上運行,前提是相應的操作系統安裝了對應的 ...
  • 開發環境: Windows操作系統開發工具:Myeclipse+Jdk+Tomcat7+MYSQL資料庫運行效果圖 源碼及原文鏈接:https://javadao.xyz/forum.php?mod=viewthread&tid=138 ...
  • 開發環境: Windows操作系統開發工具:Myeclipse/eclipse+Jdk+Tomcat+MYSQL資料庫運行效果圖 源碼及原文鏈接:https://javadao.xyz/forum.php?mod=viewthread&tid=137 ...
  • "參考文章鏈接" 我的環境 conda 4.7.10、python 3.6.7、Django 3.0.3 安裝uWSGI 這裡如果出現了問題,可以考慮如下解決辦法: "參考鏈接" 最後重新運行安裝命令 測試uWSGI是否正常工作 新建一個test.py文件: 若之後要刪除則運行 輸入如下內容: 運行 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...