当前位置: 首页 > 工具软件 > Tornado-Minos > 使用案例 >

tornado系列一:tornado基础

晁开宇
2023-12-01

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状态码:

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)响应码。

当上述任何一种错误发生时,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()


(4)几个常用函数说明:

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请求(GETPOSTPUTDELETEHEADOPTIONS)都可以用以上方法定义


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,启动报文的收发



 类似资料: