Flask【python】

文章目录

Flask

Flask 程序 = 服务端(Server)

运行 Flask 代码后,会启动一个 HTTP 服务(监听指定端口,如 8080),本质是「被动接收请求、处理请求、返回响应」的角色 ------ 就像一家 "餐厅",等待顾客(客户端)上门点餐

其他程序 / 工具 = 客户端(Client)

主动向 Flask 服务端发送 HTTP 请求(如 GET/POST)的角色,比如:浏览器、Postman、手机 App、另一个 Python 脚本、前端 Vue/React 项目等 ------ 就像 "顾客",主动发起需求(点餐),接收服务端的响应(拿到食物)

常见业务逻辑

1 客户端(如浏览器)→ 发送 HTTP 请求(如访问 http://127.0.0.1:8080/api/data)→ Flask 服务端(监听 8080 端口)接收请求 → 执行路由逻辑(查询数据、处理业务)→ 服务端返回响应(JSON/HTML 等)→ 客户端接收响应并展示(如浏览器显示数据)

2 Python 脚本(客户端)通过 HTTP 协议(POST/GET 等)向 Flask 服务端发送请求,服务端执行业务逻辑后返回响应,全程是 "客户端主动发起,服务端被动响应"

项目里面如何适用flask

复制代码
`app = Flask(__name__)`

作用:创建 Flask 应用实例

  • Flask 是 Flask 框架的核心类,通过实例化这个类创建一个 Web 应用对象(app)。

复制代码
  __name__

是 Python 的内置变量,表示当前模块的名称。Flask 用它来:

  • 确定应用的根目录(用于查找静态文件、模板文件等资源的基准路径)。

  • 避免在不同模块中重复创建应用实例

    app.config['JSON_SORT_KEYS'] = False # 禁用 JSON 键自动排序

作用:禁用 JSON 响应中字典键的自动排序
  • Flask 在返回 JSON 响应(如 jsonify({"b": 2, "a": 1}))时,默认会对字典的键进行字母序排序 ,导致返回的 JSON 中键的顺序是 {"a":1, "b":2}(而非代码中定义的 {"b":2, "a":1})。
  • 设置 app.config['JSON_SORT_KEYS'] = False 后,JSON 响应中键的顺序会与代码中定义的字典顺序一致,避免自动排序导致的前端解析问题

get post

直接用浏览器访问(默认 GET 方法)

GET 请求通常没有 JSON 体

module/routes.py 确实创建了一个Flask服务,其他Python脚本通过发送HTTP请求与之通信

具体架构分析

1. Flask服务端 (routes.py)

  • 第18行:server_app = Flask(__name__) 创建Flask应用
  • 第41行:在 main.py 中启动HTTP服务:start_thread(server_app.run, args=('0.0.0.0', Config.CONFIG['port'], False))
  • 提供多个REST API接口,包括:
    • /getConfigList - 获取配置文件列表
    • /saveConfig - 保存配置
    • /get_error - 获取错误数据
    • /get_new_ok_img - 获取最新OK图片
    • /report - 数据平台接口
    • /gui/send_res - 接收GUI结果
    • 等等...

2. HTTP客户端 (其他模块)

AI模块 (ai_module.py):

  • 第72行:向AI服务发送POST请求
python 复制代码
res = requests.post(f'http://{self.ai_url}//detect_box', data=json.dumps(send_data), headers={'content-type': 'application/json'}, timeout=self.ai_timeout)

GUI模块 (gui_module.py):

  • 第38行:向GUI服务发送POST请求
python 复制代码
response = requests.post(url, json=request_dict, timeout=20)

3. 系统架构

这是一个微服务架构,其中:

  • 主程序:运行Flask服务器作为中央协调器
  • AI服务:独立的AI检测服务
  • GUI服务:用户界面服务
  • 数据库模块:处理数据存储

总结

你的理解完全正确:

  • routes.py 创建Flask服务作为HTTP服务端
  • 其他Python脚本(如AI模块、GUI模块)作为HTTP客户端发送请求
  • Flask服务处理请求并返回HTTP响应
  • 这种设计实现了模块间的松耦合通信

这是一个典型的基于HTTP REST API的分布式系统架构。

请求头

在 HTTP 通信中,headers(请求头)是客户端告诉服务端「如何处理请求数据」的 "说明书",核心作用是让服务端正确解析请求内容

复制代码
# 1. 定义请求参数
url = "http://127.0.0.1:8080/api/v1/data/report"
headers = {"Content-Type": "application/json"}  # 必须加的请求头
data = {
    "start_time": 1620000000,  # 起始时间戳
    "end_time": 1620003600     # 结束时间戳(比起始时间多 1 小时)
}

# 2. 发送 POST 请求
response = requests.post(url=url, headers=headers, json=data)  # json 参数自动序列化并设置请求头

代码中,data 是一个 Python 字典(最终会被序列化为 JSON 字符串),而 Content-Type: application/json 的作用是明确告诉 Flask 服务端:"本次请求的 body 是 JSON 格式数据,请用 JSON 解析器处理"

不加这个请求头会怎样?

如果省略 headersrequests.post 会默认使用 Content-Type: application/x-www-form-urlencoded(表单格式),此时:

  • Flask 服务端会将请求体解析为「表单数据」(而非 JSON);
  • 你的代码中用 request.get_json() 读取数据时,会返回 None(因为服务端认为这是表单数据,不是 JSON);
  • 最终导致服务端报错(如 "缺少 start_time 参数"),客户端收到 400 Bad Request 错误

**响应内容 为什么是 {'data': [{'data': 'sample_data', 'time': 1620000000}]} ? **

Flask 用 jsonify() 生成响应时,会调用 Python 内置的 json 模块对字典进行序列化。而 json 模块的默认行为是:

  • 对字典的键进行字母序排序(无论 Python 字典本身的键顺序如何)

debug=True

复制代码
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

**自动重载(Auto-reload)**当你修改 Flask 应用的代码(如路由逻辑、函数定义)并保存后,Flask 会自动检测到代码变化,无需手动重启服务,直接加载新代码

装饰器

下面通过一个简单的"加法计算"示例,直观展示有无装饰器的区别。示例中,装饰器用于统一添加"日志记录"和"参数校验"功能

场景说明:

实现一个"加法计算"功能,需要:

  1. 记录每次计算的日志(输入参数、结果);
  2. 校验输入参数是否为数字(非数字则提示错误)。

一、无装饰器的实现(传统方式)

python 复制代码
def add(a, b):
    # 1. 手动添加参数校验(重复逻辑)
    if not (isinstance(a, (int, float)) and isinstance(b, (int, float))):
        print("错误:参数必须是数字!")
        return None
    
    # 2. 核心业务逻辑(加法)
    result = a + b
    
    # 3. 手动添加日志记录(重复逻辑)
    print(f"日志:计算 {a} + {b} = {result}")
    return result


# 测试
print(add(2, 3))       # 正常计算
print(add("2", 3))     # 参数错误

输出:

复制代码
日志:计算 2 + 3 = 5
5
错误:参数必须是数字!
None

问题分析:

  • 代码冗余 :如果有多个函数(如 subtractmultiply),每个函数都要重复写"参数校验"和"日志记录"代码;
  • 维护困难:若要修改日志格式或校验规则,需逐个修改所有函数。

二、有装饰器的实现(优化方式)

将"日志记录"和"参数校验"封装成装饰器,实现逻辑复用:

python 复制代码
def log_and_validate(func):
    """装饰器:统一添加日志记录和参数校验"""
    def wrapper(a, b):
        # 1. 参数校验(通用逻辑,只需写一次)
        if not (isinstance(a, (int, float)) and isinstance(b, (int, float))):
            print("错误:参数必须是数字!")
            return None
        
        # 2. 执行原函数(核心业务逻辑)
        result = func(a, b)
        
        # 3. 日志记录(通用逻辑,只需写一次)
        print(f"日志:计算 {a} + {b} = {result}")
        return result
    return wrapper


# 用装饰器修饰加法函数(无需重复写通用逻辑)
@log_and_validate
def add(a, b):
    # 仅保留核心业务逻辑(加法)
    return a + b


# 测试(效果与无装饰器时一致)
print(add(2, 3))       # 正常计算
print(add("2", 3))     # 参数错误
输出:
复制代码
日志:计算 2 + 3 = 5
5
错误:参数必须是数字!
None
优势分析:
  • 代码简洁add 函数仅需关注核心逻辑(加法),通用逻辑由装饰器统一处理;

  • 复用性强 :若新增 subtract 函数,只需用 @log_and_validate 修饰,自动获得相同的校验和日志功能:

    python 复制代码
    @log_and_validate
    def subtract(a, b):
        return a - b  # 无需重复写校验和日志
  • 易于维护 :修改日志格式或校验规则时,只需修改 log_and_validate 装饰器,所有被修饰的函数都会生效。

相关推荐
weixin_46683 小时前
Python编程之面向对象
开发语言·人工智能·python
渣哥3 小时前
你以为 Bean 只是 new 出来?Spring BeanFactory 背后的秘密让人惊讶
javascript·后端·面试
桦说编程3 小时前
CompletableFuture API 过于复杂?选取7个最常用的方法,解决95%的问题
java·后端·函数式编程
冲鸭ONE3 小时前
新手搭建Spring Boot项目
spring boot·后端·程序员
Moonbit3 小时前
MoonBit Pearls Vol.10:prettyprinter:使用函数组合解决结构化数据打印问题
前端·后端·程序员
Lynnxiaowen4 小时前
今天我们学习python编程常用模块与面向对象
运维·python·学习·云计算
世界哪有真情4 小时前
Trae 蓝屏问题
前端·后端·trae
一头生产的驴4 小时前
java整合itext pdf实现固定模版pdf导出
java·python·pdf
魔都吴所谓4 小时前
【python】快速实现pdf批量去除指定位置水印
java·python·pdf