实习手册三(Python基于Tornado框架的接口响应服务)Tornado框架中日志的记录,路由的分发,接口的响应

目录

前言

一、在Handler.on_finish部分记录每次接口请求的路径、时间、耗时,输出日志。

二、重写Handler中的get和post方法,实现请求能够分发到Handler的不同处理函数。


前言

还没有接触过Tornado框架的可以看这章:

实习手册二(基于Tornado框架的接口响应服务)

没有学习过框架的同学可以先看看下面这个视频教程:

tornado快速入门教程

以及网页教程:

酷python-tornado基础教程

本章我们要在Tornado框架中实现两个功能:

一、在Handler.on_finish部分记录每次接口请求的路径、时间、耗时,输出日志。

二、重写Handler中的get和post方法,实现请求能够分发到Handler的不同处理函数。

一、在Handler.on_finish部分记录每次接口请求的路径、时间、耗时,输出日志。

1、首先,Handler.on_finish部分是什么?

我们访问网页时的请求都是通过请求处理器来对我们的请求进行处理,从而返回对应的操作,在Tornado框架中,我们通过不同路由来响应不同的请求,不同请求有着对应的处理器(Handler)来对它们进行处理,这些处理器都继承同一个父类:Tornado.web中的RequsetHandler类。我们通过command+鼠标左键点击,即可查看RequestHandler中的对应方法。

 其中,我们可以看到get,post,on_finish方法等。

根据英文提示,我们可以看到在on_finish方法里,提示我们可以通过重写此方法来进行进程的清空,日志的记录和输出等。

关于日志(logging),没有学习过的小伙伴可以看这篇:

python + logging 实现日志输出及保存到文件

要在Handler中实现日志的输出与打印,我们可以用到python自带的logging包,用import logging命令即可调用。

# 调用tornado库
from tornado.web import RequestHandler, Application
from tornado.ioloop import IOLoop
import logging

# Hello处理器
class HelloHandler(RequestHandler):
    # 日志方法
    def log(self,msg): # msg为日志输出的信息
        logger = logging.getLogger('logger')
        logger.setLevel(level=logging.DEBUG)

        formatter = logging.Formatter('%(asctime)s - %(levelname)s: %(message)s')

        # 规定日志保存的路径
        file_handler = logging.FileHandler('../test2/logs/log.txt')
        file_handler.setLevel(level=logging.INFO)
        file_handler.setFormatter(formatter)

        stream_handler = logging.StreamHandler()
        stream_handler.setLevel(logging.DEBUG)
        stream_handler.setFormatter(formatter)

        logger.addHandler(file_handler)
        logger.addHandler(stream_handler)
        logger.info(msg)

    # get方法重写
    def get(self):
        self.write("Hello,world")

    # on_finish方法重写
    def on_finish(self):
        # 获取请求路径,请求方法,请求头,拼接成字符串,传入log方法,作为日志所保存的内容
        msg = str(self.request.path) + str(self.request.method) + str(self.request.headers)
        # 调用log方法
        self.log(msg)

# 路由设置
app = Application([
    (r"/", HelloHandler),
])

# 程序启动
if __name__ == "__main__":
    # 设置端口号
    app.listen(8888)
    IOLoop.current().start()

然后再次在浏览器中输入网址来测试我们的代码是否成功实现日志功能,可以看到,在控制台中已经输出了我们的日志信息:

然后打开我们logs文件夹中的log.txt,也可以查看到我们的日志信息:

注意,在运行文件时,首先要确保是否存在对应的文件夹来让日志进行保存,没有的话需要创建,不然运行时会报错。

二、重写Handler中的get和post方法,实现请求能够分发到Handler的不同处理函数。

上面介绍过我们可以通过command+鼠标左键来查看类或者方法,可以看到Tornado.web的RequestHandler类中存在get和post方法,下面先简单介绍一下它们:

get和post可以理解成传递请求参数的不同方法,get传递的参数一般是用于查询的参数,get请求的数据会附在URL之后,以?分割URL和传输数据,参数之间以&相连,并且get的长度受限于url的长度,而url的长度限制是特定的浏览器和服务器设置的,理论上get的长度可以无限长。

post把提交的数据则放置在是HTTP包的包体中,post是没有大小限制的,HTTP协议规范也没有进行大小限制,起限制作用的是服务器的处理程序的处理能力,post一般处理私密性的信息,如登陆账户,修改密码等私密性操作。

要实现用get和post请求来实现请求能够分发到Handler的不同处理函数,这里就牵扯到怎么实现接口的调用了,那么,什么是接口呢?

接口是一种用来定义程序的协议,描述可属于任何类或结构的一组相关行为
按理解来说,接口是后端处理数据然后返回的一个连接处,接着前端可以通过这个接口拿到后端的数据。在Handler中,我们可以把接口理解成一种处理请求的方法,不同的接口对应着不同的请求处理方法。

首先,想要实现请求的分发,就需要在get和post方法中对用户访问的路径进行处理,获取请求路径的方法在上个任务中已经有所提及(request.path)

此外,这里还得介绍一下Tornado.web中的Application类其中的路由参数。不同的路由决定不同的大功能,而每个大功能中又有各自的小功能,举个例子,比如用户的注册,查询,修改是三个大功能,而修改中有着修改密码,修改头像这些小功能,路由就是用来实现大功能的不同请求路径,而get和post分发来实现不同的小功能的分发。

根据代码来理解会更加的清晰:

路由设置的代码(示例):

app = Application([
    (r'/user/register/.*', RegisterHandler),
    (r'/user/search/.*', SearchHandler),
    (r'/user/change/.*', ChangeHandler)
])

其中Application中的一条数据就代表了一个大的功能,其中,

'/user/change/.*'

代表了功能的请求路径,后面的(.*)是正则表达式的用法,你可以把它理解成后面会跟接着对应的小功能的路径如:

'/user/change/change_pwd'或者'/user/change/change_username'

所以,可以这么理解,功能的分发就取决于请求路径的最后一段,当然也有别的情况,只需要设计不同的逻辑进行处理即可。

因此,在get和post请求中,我们需要对请求的路径进行处理,来找到用于分发的字段,从而调用对应的接口方法进行处理。

# 调用tornado库
from tornado.web import RequestHandler, Application
from tornado.ioloop import IOLoop
import logging

# Meet处理器
class MeetHandler(RequestHandler):
    # 日志方法
    def log(self,msg): # msg为日志输出的信息
        logger = logging.getLogger('logger')
        logger.setLevel(level=logging.DEBUG)

        formatter = logging.Formatter('%(asctime)s - %(levelname)s: %(message)s')

        # 规定日志保存的路径
        file_handler = logging.FileHandler('../test2/logs/log.txt')
        file_handler.setLevel(level=logging.INFO)
        file_handler.setFormatter(formatter)

        stream_handler = logging.StreamHandler()
        stream_handler.setLevel(logging.DEBUG)
        stream_handler.setFormatter(formatter)

        logger.addHandler(file_handler)
        logger.addHandler(stream_handler)
        logger.info(msg)

    # get方法重写
    def get(self):
        # 将路径以'/'来划分,组合成一个列表
        path = self.request.path.split('/')

        # 调用对应的接口方法是根据path列表中的最后一个字段
        method = path[-1]
        
        # 使用callable函数判断方法是否能够调用,getattr函数用来判断方法能否调用到
        if callable(getattr(self, method)):
            getattr(self, method)()
        else:
            self.write("404 not found")

    # hello接口
    def hello(self):
        self.write("Hello, world")

    # goodbye接口
    def goodbye(self):
        self.write("Goodbye, world")

    # on_finish方法重写
    def on_finish(self):
        # 获取请求路径,请求方法,请求头,拼接成字符串,传入log方法,作为日志所保存的内容
        msg = str(self.request.path) + str(self.request.method) + str(self.request.headers)
        # 调用log方法
        self.log(msg)


# 路由设置
app = Application([
    (r"/meet/.*", MeetHandler)
])

# 程序启动
if __name__ == "__main__":
    # 设置端口号
    app.listen(8888)
    IOLoop.current().start()

可以看到,我们在MeetHandler中写了hello和goodbye两个简单的接口,现在我们再次访问服务界面

访问http://127.0.0.1:8888/meet/hello

访问http://127.0.0.1:8888/meet/goodbye

 这样便实现了请求的分发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值