tornado學習一:一個基本的tornado服務器


1.編譯安裝tornado:

$ curl -L -O https://github.com/facebook/tornado/archive/v3.1.0.tar.gz
$ tar xvzf v3.1.0.tar.gz
$ cd tornado-3.1.0
$ python setup.py build
$ sudo python setup.py install

Tornado官方並不支持Windows,但你可以通過ActivePython的PyPM包管理器進行安裝,類似如下所示:

C:\> pypm install tornado

 

2.一個簡單的tornado服務器:server.py

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', friendly user!')

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

 

運行服務器:

$ python server.py --port=8000

 

測試:在瀏覽器中打開http://localhost:8000,或者 使用curl測試

$ curl http://localhost:8000/
Hello, friendly user!
$ curl http://localhost:8000/?greeting=Salutations
Salutations, friendly user!

 

3.分析:

一個最基本的tornado服務器,必須至少包含這四個模塊:tornado.options、tornado.web、tornado.httpserver、tornado.ioloop

1)tornado.options:用來從命令行讀取設置。當然,也可以將設置寫死,不從命令行讀取。

定義示例:

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

使用示例:

$ python server.py --port=9000

 

from tornado.options import define, options
print (options.port)     # options.port將作為全局設置,返回值9000

 

工作流程:

如果一個與define語句中同名的設置在命令行中被給出,那么它將成為全局options的一個屬性。

  • 第一個參數:參數名稱
  • default參數:如果沒有在命令行中給出此名稱的參數,則使用default的值進行代替。
  • type參數:進行基本的參數類型驗證

在命令行中,使用--help選項,將打印出所有你定義的選項以及你在define函數的help參數中指定的文本。

 

2)tornado.web.RequestHandler:請求處理函數的類

示例:

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', friendly user!')

 

當處理一個請求時:Tornado將這個類IndexHandler實例化,並調用與HTTP請求方法(如此處的HTTP請求方法,假設為:GET),所對應的方法(如這里定義的self.get()方法)。

也就是說,當一個get請求到來時,將實例化IndexHandler,並且調用此實例的self.get()方法,如果有。

當一個post請求到來時,將將實例化IndexHandler,並且調用此實例的self.post()方法,如果有。---這里沒有定義post方法,因此對於POST請求,是不會處理的。

同時,RequestHandler類的實例,有一系列的方法,

RequestHandler類的參數處理方法:

  • self.get_argument('apiName', 'default_value') 獲取名稱為"apiName"的參數(包括query和post在內的所有參數)
  • self.request.query_arguments 獲取所有的查詢參數
  • self.request.body.decode('utf-8') 獲取所有的post參數
  • self.request.body_arguments 獲取所有的post參數

RequestHandler類的響應方法:

  • self.write(string)  將一個字符串寫入到HTTP響應中
  • self.finish(string)  將一個字符串寫入到HTTP響應中
  • self.render(a_html_file) 將一個html模板渲染到HTTP響應中

RequestHandler類顯示設置狀態碼:self.set_status()

Tornado會自動地設置HTTP狀態碼,如400,404,405,500,200........

當上述任何一種錯誤發生時,Tornado將默認向客戶端發送一個包含狀態碼和錯誤信息的簡短片段。

如果你想使用自己的方法代替默認的錯誤響應,你可以在你的RequestHandler類中,重寫write_error方法。

RequestHandler類的錯誤處理方法:self.write_error()

示例:

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', friendly user!')
    def write_error(self, status_code, **kwargs):
        self.write("Gosh darnit, user! You caused a %d error." % status_code)

 

當我們嘗試一個POST請求時,如果沒有覆寫write_error方法,會得到Tornado默認的錯誤響應。

tornado.web.HTTPError: HTTP 405: Method Not Allowed

 

但因為我們覆寫了write_error,我們會得到不一樣的錯誤響應:

$ curl -d foo=bar http://localhost:8000/
Gosh darnit, user! You caused a 405 error.

 

3)tornado.web.Application:路由app

示例

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
tornado.options.parse_command_line():用來解析命令行中的參數
Application(handlers=[(r"/", IndexHandler)]),創建路由app實例:它告訴Tornado,用哪個類來響應哪個url的請求
這里非常重要,handlers指明了路由,是一個列表,列表內是多個元組;元組的第一個參數是一個用於匹配的正則表達式,指明url路徑;第二個參數handlers,相當於django的視力函數。
Tornado在元組中使用正則表達式來匹配HTTP請求的路徑。(這個路徑是URL中主機名后面的部分,不包括查詢字符串和碎片。)Tornado把這些正則表達式看作已經包含了行開始和結束錨點(即,字符串"/"被看作為"^/$")。
Application,除了指明路由,還可以指明其它參數,如:
bases = dict(
    # blog_title=u"F2E Community",
    template_path=os.path.join(os.path.dirname(__file__), os.pardir, "templates"),
    static_path=os.path.join(os.path.dirname(__file__), "static"),
    xsrf_cookies=xsrf_cookies,  # True或False
    debug=base.ENV == "DEBUG" and True or False,
    cookie_secret="cookie_secret_code",
    # login_url="/login",
    autoescape=None,
    # reserved=["user", "topic", "home", "base", "forgot", "login", "logout", "register", "admin"],
    handlers=route_list,
    autoreload=True
)
Application(**bases)

 

4)運行服務器:

http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()

 

從這里開始的代碼將會被反復使用:一旦Application對象被創建,將其傳遞給Tornado的HTTPServer對象,然后使用在命令行指定的端口進行監聽(通過options對象取出)。最后,在程序准備好接收HTTP請求后,我們創建一個Tornado的IOLoop的實例。

 

 

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM