1、tornado是什么
tornado是一个python编写的强大的可扩展的web服务器,它采用非阻塞的socket,可以高性能处理大并发长连接场景下的web应用。
2、tornado如何部署
tornado在 linux系统中天然支持。并且在python2.6以上的版本中,tornado代码都包含在python标准库中,在使用tornado时,除了python标准库之外,不需要安装任何其它额外的软件
如果要用tornado建立一个HTTPserver,用来处理HTTP请求,则只需要写一个.py文件,在文件中调用tornado各基本模块的功能,进行服务的实例化并启动服务即可。
3、tornado简单web服务的实例:
创建一个文件 hello.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 givern 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.Applicaion(handlers=[(r"/",IndexHandler)])
httpserver=tornado.httpserver.HTTPServer(app)
httpserver.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
---------------------------------------------------------------------------------------------------------------------------------------------
说明:
3.1 一个简单的tornado server一般需要以下四个模块
import tornado.httpserver #server主体
import tornado.ioloop #底层IO
import tornado.options #应用的命令解析
import tornado.web #web的处理
3.2 应用命令解析
我们在启动一个.py程序的时候,有时候要跟上一些命令,以作为程序的输入参数,例如:
$python hello.py --port=8000
tornado的options模块就是实现命令的定义、赋初值、命令解析
3.2.1命令的定义和赋值
from tornado.options import define,options
define("port", default=8000,help="run on the givern port", type=int)
define() ---用来定义命令,其中:
"port" ---命令格式
default=8000 --命令初值,如果我们启动该.py时,没有指定--port=8000,则我们默认指定port=8000
help="run on the givern port" --port命令的帮助信息,我们在执行 $ python hello.py --help时,会显示该帮助信息
type=int --port命令所能接受的输入值类型,如果该类型错误,options将会抛出一个异常
3.2.2命令的解析
tornado.options.parse_command_line()
该函数用来对输入的命令进行解析,如果所定义命令未指定,则为其附初值
3.2.2命令的值的引用
httpserver.listen(options.port)
options.command 其中的command为define()定义的命令,通过该命令名,可直接对其值进行引用
3.3 web的处理
3.3.1 定义请求处理类
tornado中用来处理HTTP请求的类为tornado.web.RequestHandler,我们在定义HTTP请求的处理类时,只需继承该类。
(1) 对不同类型的请求定义不同的处理类
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)))
上栗中,对get方法和post方法,分别定义了一个处理类,我们可以将类应用到不同的处理路径中,如:
app = tornado.web.Application( handlers=[ (r"/reverse/(\w+)", ReverseHandler), (r"/wrap", WrapHandler) ] )
(2)在同一个处理类中定义不同的处理函数
该方式应用在,对同一个请求提供多种不同的处理方式的场景中# matched with (r"/frob/(\d+)", FrobHandler) class FrobHandler(tornado.web.RequestHandler): def head(self, frob_id): frob = retrieve_from_db(frob_id) if frob is not None: self.set_status(200) else: self.set_status(404) def get(self, frob_id): frob = retrieve_from_db(frob_id) self.write(frob.serialize())
(3)自定义错误响应
在某些情况下,Tornado会自动地设置HTTP状态码:
Tornado会在HTTP请求的路径无法匹配任何RequestHandler类相对应的模式时返回404(Not Found)响应码。
如果你调用了一个没有默认值的get_argument函数,并且没有发现给定名称的参数,Tornado将自动返回一个400(Bad Request)响应码。
如果传入的请求使用了RequestHandler中没有定义的HTTP方法(比如,一个POST请求,但是处理函数中只有定义了get方法),Tornado将返回一个405(Methos Not Allowed)响应码。
当程序遇到任何不能让其退出的错误时,Tornado将返回500(Internal Server Error)响应码。你代码中任何没有捕获的异常也会导致500响应码。
如果响应成功,并且没有其他返回码被设置,Tornado将默认返回一个200(OK)响应码。
当上述任何一种错误发生时,Tornado将默认向客户端发送一个包含状态码和错误信息的简短片段。如果你想使用自己的方法代替默认的错误响应,你可以重写 write_error 方法在你的 RequestHandler 类中,例如:
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!') def write_error(self, status_code, **kwargs): self.write("Gosh darnit, user! You caused a %d error." % status_code) 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()
get_argument(self, name [, default=[], strip=True]) 获得请求中的name指令的值,如果请求中未提供name指令,则使用该函数中的默认值,如果该函数未提供默认值,则返回一个404错误。如果该指令在请求中出现了多次,则以最后一个为准。该函数可用在GET 或POST请求中。
write(self, chunk) 它以一个字符串作为函数的参数,并将其写入到HTTP响应中
set_status(self, status_code) 显式地设置HTTP状态码
(5) HTTP请求
Tornado支持的任何合法HTTP请求(GET、POST、PUT、DELETE、HEAD、OPTIONS)都可以用以上方法定义
3.3.2 实例化Application类,定义请求和类的RequestHandler类的响应关系
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)))
app = tornado.web.Application( handlers=[ (r"/reverse/(\w+)", ReverseHandler), (r"/wrap", WrapHandler) ] )
传递给Application类构造函数的是一个handler,handler是一个元组列表,每个元组对应一个请求响应关系。
注意:其中的get方法不但可以用get_argument获得指令的值,还可以通过输入参数的方式获得,其中的input[::-1]用于将字符串翻转,该方法也可用于列表和元组。
3.4实例化httpserver并启动端口监听
http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port)
3.5 实例化底层IO并启动报文收发
tornado.ioloop.IOLoop.instance().start()
至此,一个简单的tornado server就搭建起来了,总结起来步骤如下:
(1) 定义并处理server执行的输入命令
(2) 定义HTTP请求处理类,实例化Application,定义请求和响应类的关系
(3) 实例化httpserver,启动httpserver的监听
(4) 实例化底层IO,启动报文的收发