Flask 是 python 中非常流行的一个 web 框架,容易学习。这篇文章主要通过 2 个实际案例讲解 Flask 如何使用。第一个例子是实现一个调用公交车到站信息的接口服务;第二个例子是通过接口展示所有的测试报告。
pip install flask
from flask import Flask app = Flask(__name__) app.run() 复制代码
通过 3 行代码,可以启动一个 flask 的服务。
运行这个代码,可以在本地的 5000 端口访问, 得到结果是 404 页面无法找到:
此时,访问 http://localhost:5000 看到 404 错误,是因为没有定义接口。 一个 url 地址和一个处理函数对应,就可以形成一个接口。 通过下面的代码,可以在之前的代码基础上添加一个接口:
@app.route('/') def index(): return { "msg": "success", "data": "welcome to use flask." } 复制代码
接口添加完成后,再次访问 http://localhost:5000, 就可以看到正常的响应数据了:
如果还需要定义另外的接口,只需要参照上面的例子继续定义。 比如实现一个注册接口:
@app.route('/user/<u_id>') def user_info(u_id): return { "msg": "success", "data": { "id": u_id, "username": 'yuz', "age": 18 } } 复制代码
此时访问 /user/3
将会得到 id 为 3 的用户信息:
Flask 完全可以胜任中大型项目,但是这不是它的目标。如果想做一个完完全全的 web 项目,建议用 Django。Flask 更适合用在一些小型项目上,比如当你执行完一些计算任务,想通过 web 的形式为用户提供数据服务或者是展示服务。 你不需要像 django 一样,去维护太多的模块。
举个例子。我现在写了一个程序,计算接下来一段时间有哪些公交车会经过三元里这个站。计算得到的结果可以通过多种形式展现给别人看:
控制台输出
存到数据库
展示到 api 上
展示到手机 app 上
展示到 web 网页上
我现在可以通过 flask 创建一个 api , 为用户展示这些数据。 但是要注意,展示数据只是一个小功能,核心程序应该是我怎样计算出公交站的信息,这些才是这个程序的真正价值所在,我可以通过上面的任意一种方式去展现,并不只有 web 开发一种形式。因为展示的逻辑非常简单,并不需要使用 django 这样的巨型框架。
真实的公交信息计算程序是非常复杂的,这里我通过一个简单的程序模拟计算公交车数据的过程。这个程序会随机生成 10 组公交车数据,存放到一个列表当中。
import random def get_bus_info(station): info = [] for random_bus in range(10): bus_name = f"W{random.randint(1, 100)}" bus_arrival_time = random.randint(1, 30) bus_info = f"{bus_name} 还有 {bus_arrival_time} 分钟到达 {station}" info.append({bus_name: bus_info}) return info 复制代码
可以直接调用这个函数获取相关的公交车数据:
for bus in get_bus_info('三元里'): print(bus) 复制代码
可以在控制台得到的输出结果类似于这样:
现在我可以用 flask 创建一个 api, 让所有的用户和其他想要我数据的服务商都可以拿到这些数据,
至于他们是直接读取,还是用页面展示出来,随便吧,这不是我关心的。我只负责运算,然后提供数据,如果这个技术很厉害,我就可以通过这些数据收费,用户就得为我提供的接口付费。
接下来我要创建一个 /bus/<station>
的接口, 当我往 url 输入 station 公交站的名字,接口会给我返回这个公交站的公交信息。
定义接口:
@app.route('/bus/<station>') def bus_info(station): import bus info = bus.get_bus_info(station) return { "msg": "success", "data": info } 复制代码
访问 /bus/天安门
接口得到数据:
上一个例子中,我通过 Flask 提供了一个 api 展示公交运营数据。接下来再通过一个展示测试报告的例子理解 flask 提供 api 的功能。
写代码通常需要测试,测试完成以后生成的测试报告数据通常会存放在本地。存放的形式有多种:
这里以 html 文件举例。 先写一个测试程序生成 html 测试报告:
import pytest from datetime import datetime def test_add(): assert 1 == 2 def gen_report_name(): prefix = '测试报告' ts = datetime.now().strftime('%Y-%m-%d-%H-%M-%S') return prefix + ts + '.html' if __name__ == '__main__': report_name = gen_report_name() pytest.main([f'--html=output/{report_name}']) 复制代码
每次运行测试用例程序以后会在 output 目录下生成测试报告。这些报告以 测试报告
为前缀,当前时间为文件名:
现在我要设计一个 API, 地址为 /report/<filename>
。 当我输入 report/测试报告2020-04-28-13-53-42.html
时,能够查看此次的测试报告内容:
要实现这个功能,只需要在 api.py 文件中添加对应的程序。这个程序打开在 output 目录下的测试报告文件,返回给前端:
@app.route('/report/<file_name>') def get_report(file_name): """根据文件名获取测试报告。""" import pathlib file_path = pathlib.Path(__file__).parent / 'output' / file_name f = open(file_path, encoding='utf-8') report = f.read() f.close() return Response(report) 复制代码
现在,虽然我能通过 API 查看测试报告,但是我需要提前知道测试报告的名称才能输入对应 url。而如果要提供给别人使用,他们是不知道这些报告叫什么名字的。
我现在可以设计另外的 API /reports
, 当用户访问这个接口时,能够直接得到所有的测试报告地址。然后,复制这些地址就可以查看每次的测试报告:
为了实现这个接口,首先我会写一个函数自动收集 output 目录下所有的测试报告,规则是以 .html
为后缀的文件:
def discover_reports(): """查找所有的测试报告""" import pathlib report_dir = pathlib.Path(__file__).parent / 'output' reports = [f.name for f in report_dir.iterdir() if f.suffix == '.html'] return reports 复制代码
当我调用这个函数,返回 output 目录下所有测试报告文件名:
接下来,我在 api.py 中添加对应的接口,调用这个 discover_report 函数就可以了:
@app.route('/reports') def get_reports(): import test_helper report_names = test_helper.discover_reports() return { "msg": "success", "data": [f"http://localhost:5000/report/{name}" for name in report_names ] } 复制代码
最后看一下查看所有测试报告的执行效果:
Flask 是一个非常随心的框架。如果你想使用 Flask, 你不需要去了解他的全部,要用的时候再去学习。在上面这个计算公交站信息的程序中,web 展示的代码只有 7 行,而模拟公交数据的程序达到了 9 行。
我对 Flask 的理解是,web 只是展示数据的途径,而不是目标。而在实际的生活中,有太多的公司或者开发者把 web 当成了生命中的全部。 这是设计理念上的区别。
如果你喜欢极简主义,你真应该试试它。