Python一天一道面试题-自写简单版flask框架

2797 篇文章 2 订阅
2644 篇文章 26 订阅

什么是flask框架?

Flask是一种基于Python编程语言的轻量级Web应用程序框架。它提供了一个简单易用的方式来构建Web应用程序,具有灵活性和可扩展性。

Flask框架的主要作用是帮助开发人员构建Web应用程序,并提供许多常见的Web开发功能,如路由、模板引擎、请求和响应处理、会话管理等。使用Flask框架,开发人员可以快速创建Web应用程序并将其部署到生产环境中。

Flask框架还支持许多扩展,例如ORM(对象关系映射器)和表单验证,使得开发人员能够更加高效地开发Web应用程序。此外,Flask框架也非常适合构建REST API和微服务等互联网应用程序。

flask框架使用的demo

# 如果我们的pycharm是社区版,需要先安装flask框架
# 安装命令 pip install flask
import flask

app = flask.Flask(__name__)


@app.route('/report')
def report():
    return "报告页面"


@app.route('/login')
def login():
    return "登录页面"


@app.route('/register')
def register():
    return "注册页面"


if __name__ == '__main__':
    app.run()

执行上面代码,会在控制台弹出本地的访问地址,将其复制到网页中进行访问。

代码执行

页面访问信息

自己写一个类似的flask框,来了解flask执行原理

在自己编写一个简单的flask框架前,我们要知道flask框架的原理是什么?下面将简单的讲述一下flask的执行原理。

1.接收请求:

Flask框架通过HTTP服务器(如Gunicorn、uWSGI等)监听指定的端口,当有请求到达时,框架接收并处理该请求。

2.路由匹配:

Flask框架根据请求的URL路径,通过定义的路由规则进行匹配,确定要执行的视图函数(处理请求的函数)。

3.视图函数执行:

一旦匹配到对应的路由,Flask框架会调用与该路由关联的视图函数。视图函数处理请求并返回相应的数据。

4.请求上下文管理:

在执行视图函数之前,Flask框架会为每个请求创建一个请求上下文对象,该对象包含请求的相关信息(如请求头、请求参数等)。请求上下文对象会被绑定到当前线程,以便在视图函数中访问请求的信息。

5.视图函数返回:

视图函数执行完毕后,会返回一个响应对象,其中包含要返回给客户端的数据(如HTML内容、JSON数据等)。

6.响应处理:

Flask框架将响应对象处理成符合HTTP协议的格式,包括设置响应头信息、序列化响应数据等。

7.响应发送:

最后,Flask框架将响应发送给HTTP服务器,由服务器将响应返回给客户端。

总结一下简单来说,就是要接收的http请求进行处理判断,然后再根据自己定义的规则进行数据的返回。

编写flask框架服务器

在编写flask框架服务器前,我们要知道HTTP协议的底层使用的是基于TCP/IP协议的套接字(socket)进行通信。HTTP是一种应用层协议,而TCP/IP是一组网络通信协议,其中TCP(Transmission Control Protocol)是一种可靠的、面向连接的协议,提供数据传输的可靠性和顺序性。HTTP利用TCP/IP协议的可靠性和连接性进行数据传输,通过建立和维护套接字连接,进行请求和响应的交换。因此,HTTP协议可以看作是在TCP/IP协议之上构建的一种应用层协议,使用套接字作为底层通信机制。

所以flask框架服务器的代码实现时,其实也是可以直接继承socket通信框架来实现,不过在这,我就直接编写HttpServer服务器代码了,就不再去写socket服务器代码再去继承了。

class HttpServer:
    def __init__(self):
        # 创建一个流式套接字
        self.sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
        # 绑定端口和地址
        self.sock.bind(('127.0.0.1', 9988))
        # 设置监听
        self.sock.listen(20)
        self.routers = {}

    def run(self, thread=1):
        print("服务已启动,运行在本地:127.0.0.1:9988")
        # 创建线程池,可以多线程执行
        with ThreadPoolExecutor(max_workers=thread) as tp:
            while True:
                # 4、等待客户端连接
                client_socket, addr = self.sock.accept()
                # 将处理函数提交到线程池去处理
                tp.submit(self.handle_request, client_socket, addr)

    def handle_request(self, client_socket, addr):
        """处理http请求"""
        print("客户端{}建立连接".format(addr))
        # 1、接收请求数据报文
        data = self.recv_data(client_socket)
        # 2、解析http请求
        request = self.parser_request_data(data)
        # 3、处理请求
        res = self.match_handle_method(request)
        # 4、返回http报文
        self.return_response(client_socket, res['status'], res['body'])
        # 5、断开连接
        client_socket.close()

    def recv_data(self, client_socket):
        """接收请求数据"""
        data = b''
        while True:
            # 接收客户端传递过来的数据
            r = client_socket.recv(1024)
            data += r
            if len(r) < 1024:
                break
        # 返回字符串
        return data.decode()

    def parser_request_data(self, data):
        """解析http请求"""

        # 请求方法
        method = data.split('\r\n')[0].split(' ')[0]
        # 请求路径
        path = data.split('\r\n')[0].split(' ')[1]
        # 请求头
        head = data.split('\r\n\r\n')[0].split('\r\n')[1:]
        headers = {i.split(':')[0]: i.split(':')[1] for i in head}
        # 请求参数
        query_params = {}
        json_params = {}
        form_params = {}
        if "?" in path:
            path, query_str = path.split('?')
            query_params = {i.split('=')[0]: i.split('=')[1] for i in query_str.split('&')}
        # 请求体参数,json格式,表单
        if headers.get('Content-Type') == " application/json":
            json_params = json.loads(data.split('\r\n\r\n')[1])
        elif headers.get("Content-Type") == " application/x-www-form-urlencoded":
            form_str = data.split('\r\n\r\n')[1]
            form_params = {i.split('=')[0]: i.split('=')[1] for i in form_str.split('&')}
        res = {
            "method": method,
            "path": path,
            "headers": headers,
            "params": query_params,
            "data": form_params,
            "json": json_params
        }
        return res

    def return_response(self, client_socket, status=200, body=''):
        """返回http报文"""
        HTTPCODE = {
            200: 'HTTP/1.1 200 OK\r\n',
            404: 'HTTP/1.1 400 NOT FOUND\r\n'
        }
        header = HTTPCODE.get(status)
        header += "Content-Type:text/html;charset=utf-8\r\n"
        header += "\r\n\r\n"
        if isinstance(body, bytes):
            response = header.encode() + body
        else:
            response = header.encode() + body.encode()
        client_socket.send(response)

    def match_handle_method(self, request):
        """匹配请求处理方法处理请求,返回要返回给客户端的内容"""
        if self.routers.get(request['path']):
            handle_method = self.routers.get(request['path'])
            status = 200
            # 调用处理函数
            body = handle_method()
        else:
            status = 404
            body = '页面不存在'
        return {
            "status": status,
            "body": body
        }

# 路由装饰器
    def route(self, path):
        def wrapper(func):
            self.routers[path] = func

        return wrapper

编写路由信息

在上面我们已经编写好了HttpServer服务器的代码,现在我们可以和上面flask框架demo一样写几个路由(网页访问地址)来测试一下我们自己的HttpServer服务器代码的正确性。

from day7.HttpServer1 import HttpServer

# 实例化HttpServer对象
app = HttpServer()


@app.route("/login")
def login():
    return "这是登录页面"


@app.route("/register")
def register():
    return "这是注册页面"


@app.route("/")
def index():
    return "这是首页"


if __name__ == '__main__':
    app.run()

代码执行后显示

接着我们可以发送一个请求来看一下HttpSerer的返回结果情况。

import socket

 # 创建一个流式套接字
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接地址
client.connect(('127.0.0.1', 9988))
# 设置发送的请求信息
request_data = 'GET /login HTTP/1.1\r\nHost: 127.0.0.1:9988\r\n\r\n'
# 发送请求信息
client.send(request_data.encode())
# 接收服务器返回的响应信息
response_data = client.recv(1024).decode()
print("服务器返回结果:", response_data)
# 关闭socket连接
client.close()

发送请求后,服务器返回给我们的结果,从返回的响应结果中我们就可以看到这和flask框架的执行原理是类似的,这样一来就能证明我们的简单版flask框架就完成了。

总结

其实在实际测试开发学习中,我们不用自己去编写一个HttpServer服务器来用,我们可以直接使用现成的第三方Python库就好了,毕竟其功能完善程度肯定是比我们自己写的好很多。那为什么我这边还要再介绍、自己写一遍简单的flask框架呢?

其实道理很简单,我们一直听说或者使用flask框架,但是自己却不真正的了解其底层代码实现的原理,只是知道有这么个东西,用起来也是一知半解的。如果我们自己能简单的写一下其执行原理的代码,就能更好的了解我们使用的工具,也能更好的去进行测试开发的学习和以后框架的设计。

行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群: 786229024,里面有各种测试开发资料和技术可以一起交流哦。

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】在这里插入图片描述
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值