Tornado学习之路一
这次的博客都不知道能坚持到什么时候,所以先不预告能有多少篇吧,事不宜迟,先来了解一下tornado吧
Tornado的特性
轻量级,采用协程的多任务方式来实现异步操作,防止了像Apache服务器这种线程服务器中容易出现线程池资源占用,耗光资源的情况。
应用场景:Tornado不适合作为庞大的CMS或一体化开发框架的替代品,但如果是编写一个可扩展的社交应用、实时分析引擎,或RESTful API,那么Tornado就是一个不错的选择。
Tornado简单范例
安装的事情只要使用类Unix系统的人都很容易学会的,最简单的方式就是直接使用pip来安装
$ pip install tornado
如果遇到错误的话请试试看用root权限来安装,一般pip安装出问题都可以这样解决,如果还有问题,请去stackoverflow看看吧,基本上只有你找不到,没有不存在解决方案的道理
Tornado的简单web服务
既然是入门还是那句话Hello World是少不了的,首先是写一个简单的HTTP服务吧, 代码比较简单只是在官方给的范例里面改了点东西
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options
"""这里允许你在命令行中使用--port=[端口号]的形式来修改启动端口"""
define("port", default=8000, help="run on the given port", type=int)
class HelloHandler(tornado.web.RequestHandler):
"""定义一个Handler类,继承tornado的RequestHandler,实现了基本的响应功能,提供了get方法"""
def get(self):
greeting = self.get_argument('greeting', 'Hello')
self.write('Hello, ' + greeting)
if __name__ == "__main__":
tornado.options.parse_command_line()
app = tornado.web.Application(handlers=[(r"/hello", HelloHandler)])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
执行
执行命令:
$ python hello_tornado.py --port=8000
注意:由于options.defind当中我们定义了port参数,因此可以通过使用命令行参数的形式来修改端口,另外输入help也可以看到关于--port参数功能的介绍
和我在代码里设置的提示一致。
在Handle类中,我们通过使用self.get_argument()方法实现获取了一个HTTP GET方法中带入的参数,该方法的定义如下:
def get_argument(self, name, default=_ARG_DEFAULT, strip=True)
所以我们在这里输入的greeting为参数名,如果我们不带入该参数的话,就会使用默认值Hello
RequestHandle类中的write方法接收的是一个str类型的参数,并将其写入到HTTP的响应中,输出
要使Tornado的web服务跑起来,最重要的还是需要注册一个Application实例,在该实例中将需要映射的服务对应的path和handle对应起来,比如这里我就将HelloHandle和"/hello"这个路径对应起来,最后把该app注册给HTTPServer对象进行监听,然后创建一个IOLoop的实例就可以生效了,至于IOLoop是什么,我还不太懂,后面有机会再详细了解一下吧,不报希望的等一下吧
执行结果
至于Application实例申明的时候传入的handlers参数的路由确切来说并不是普通的字符串,而是一个表示某些路径的正则表达式
获取path上的string作为输入参数
import textwrap
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 ReverseHandler(tornado.web.RequestHandler):
def get(self, input):
self.write(input[::-1])
class WrapHandler(tornado.web.RequestHandler):
def post(self):
text = self.get_argument('text')
width = self.get_argument('width', 40)
self.write(textwrap.fill(text, int(width)))
if __name__ == "__main__":
tornado.options.parse_command_line()
app = tornado.web.Application(
handlers=[
(r"/reverse/(\w+)", ReverseHandler),
(r"/wrap", WrapHandler)
]
)
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
从代码中可看到有两种方法实现了获取url中的参数,并进行了回文输出
-
通过使用正则表达式,在源码中对于get方法的定义是
def get(self, *args, **kwargs)
输入的参数个数只要与正则表达式相匹配皆可
-
通过使用text和width这两个默认参数,可以获取到元url后面带的文本的内容和长度,这样就能获取到内容
textwrap模块用来以指定的宽度装饰文本,并将结果字符串写回到HTTP响应中。
使用哪种方法可以自己决定,不过我个人是比较习惯正则表达式的方法,虽然正则有时候很难写,但是表达的逻辑会更加舒服一些,text和width参数的形式总感觉不怎么好看
其他HTTP方法
Tornado支持任何合法的HTTP请求(GET、POST、PUT、DELETE、HEAD、OPTIONS)
设置HTTP状态码
使用RequestHandler类的set_status()方法显式地设置HTTP状态码
class HelloHandler(tornado.web.RequestHandler):
def head(self):
self.set_status(200)
然而在某些情况下tornado会自动设置status_code
404 Not Found
Tornado会在HTTP请求的路径无法匹配任何RequestHandler类相对应的模式时返回404(Not Found)响应码。
400 Bad Request
如果你调用了一个没有默认值的get_argument函数,并且没有发现给定名称的参数,Tornado将自动返回一个400(Bad Request)响应码。
405 Method Not Allowed
如果传入的请求使用了RequestHandler中没有定义的HTTP方法(比如,一个POST请求,但是处理函数中只有定义了get方法),Tornado将返回一个405(Methos Not Allowed)响应码。
500 Internal Server Error
当程序遇到任何不能让其退出的错误时,Tornado将返回500(Internal Server Error)响应码。你代码中任何没有捕获的异常也会导致500响应码。
200 OK
如果响应成功,并且没有其他返回码被设置,Tornado将默认返回一个200(OK)响应码。
另外我们也可以通过使用write_error方法来重写这些错误提示
def write_error(self, status_code, **kwargs):
self.write("Gosh darnit, user! You caused a %d error." % status_code)
里面使用的例子是来自tornado官方的教程的,这里只是简单总结了一下,下次会努力写点自己的东西的。。。