什么是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框架,但是自己却不真正的了解其底层代码实现的原理,只是知道有这么个东西,用起来也是一知半解的。如果我们自己能简单的写一下其执行原理的代码,就能更好的了解我们使用的工具,也能更好的去进行测试开发的学习和以后框架的设计。
行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!