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的實例。