17

2 个案例带你迅速入门 Python Flask 框架

 3 years ago
source link: http://www.cnblogs.com/heniu/p/12813600.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Flask 是 python 中非常流行的一个 web 框架,容易学习。这篇文章主要通过 2 个实际案例讲解 Flask 如何使用。第一个例子是实现一个调用公交车到站信息的接口服务;第二个例子是通过接口展示所有的测试报告。

Flask 安装

pip install flask

yYRRnqz.gif flask 安装

Flask 启动服务

from flask import Flask

app = Flask(__name__)

app.run()

通过 3 行代码,可以启动一个 flask 的服务。

  1. 第一行,导入
  2. 第二行,创建 Flask 程序实例
  3. 第三行,通过实例启动服务

运行这个代码,可以在本地的 5000 端口访问, 得到结果是 404 页面无法找到:

4S2oaMhlQTEwuVB.gif flask running.gif

为 Flask 程序添加接口

此时,访问 http://localhost:5000 看到 404 错误,是因为没有定义接口。 一个 url 地址和一个处理函数对应,就可以形成一个接口。 通过下面的代码,可以在之前的代码基础上添加一个接口:

@app.route('/')
def index():
    return {
        "msg": "success",
        "data": "welcome to use flask."
    }

接口添加完成后,再次访问 http://localhost:5000, 就可以看到正常的响应数据了:

Ipu2STQaCmLcX8o.png image.png

如果还需要定义另外的接口,只需要参照上面的例子继续定义。 比如实现一个注册接口:

@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 的用户信息:

b26aqscINjPYzgE.png image.png

Flask 实现公交信息查询服务

Flask 完全可以胜任中大型项目,但是这不是它的目标。如果想做一个完完全全的 web 项目,建议用 Django。Flask 更适合用在一些小型项目上,比如当你执行完一些计算任务,想通过 web 的形式为用户提供数据服务或者是展示服务。 你不需要像 django 一样,去维护太多的模块。

举个例子。我现在写了一个程序,计算接下来一段时间有哪些公交车会经过三元里这个站。计算得到的结果可以通过多种形式展现给别人看:

  1. 控制台输出

  2. 存到数据库

  3. 展示到 api 上

  4. 展示到手机 app 上

  5. 展示到 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)

可以在控制台得到的输出结果类似于这样:

lcYKGf34BgeODHy.png image.png

现在我可以用 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/天安门 接口得到数据:

tdgzm4D9yxQiKwn.png image.png

Flask 实现测试报告服务

上一个例子中,我通过 Flask 提供了一个 api 展示公交运营数据。接下来再通过一个展示测试报告的例子理解 flask 提供 api 的功能。

写代码通常需要测试,测试完成以后生成的测试报告数据通常会存放在本地。存放的形式有多种:

  1. txt 文本
  2. xml 文件
  3. html 文件
  4. json 文件
  5. yaml 文件。

这里以 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 目录下生成测试报告。这些报告以 测试报告 为前缀,当前时间为文件名:

wPuNBsmSlR5IOfx.png pytest-reports-fs8.png

现在我要设计一个 API, 地址为 /report/<filename> 。 当我输入 report/测试报告2020-04-28-13-53-42.html 时,能够查看此次的测试报告内容:

numQf2f.png!web flask check test report

要实现这个功能,只需要在 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)

Flask 查看所有的测试报告链接

现在,虽然我能通过 API 查看测试报告,但是我需要提前知道测试报告的名称才能输入对应 url。而如果要提供给别人使用,他们是不知道这些报告叫什么名字的。

我现在可以设计另外的 API /reports , 当用户访问这个接口时,能够直接得到所有的测试报告地址。然后,复制这些地址就可以查看每次的测试报告:

nM7za27.png!web flask check 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 目录下所有测试报告文件名:

VVFrQvq.png!web

接下来,我在 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
                 ]
    }

最后看一下查看所有测试报告的执行效果:

BZzMziM.gif flask check all reports

总结

Flask 是一个非常随心的框架。如果你想使用 Flask, 你不需要去了解他的全部,要用的时候再去学习。在上面这个计算公交站信息的程序中,web 展示的代码只有 7 行,而模拟公交数据的程序达到了 9 行。

我对 Flask 的理解是,web 只是展示数据的途径,而不是目标。而在实际的生活中,有太多的公司或者开发者把 web 当成了生命中的全部。 这是设计理念上的区别。

如果你喜欢极简主义,你真应该试试它。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK