Flask【python】
文章目录
- Flask
- 项目里面如何适用flask
- 作用:禁用 JSON 响应中字典键的自动排序
- get post
- 具体架构分析
- 1. **Flask服务端** ([routes.py](cci:7://file:///d:/python_code_git/yc_structure/module/routes.py:0:0-0:0))
- 2. **HTTP客户端** (其他模块)
- 3. **系统架构**
- 总结
- 请求头
- `debug=True`
- 装饰器
- 输出:
- 优势分析:
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请求
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请求
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 解析器处理”
不加这个请求头会怎样?
如果省略 headers
,requests.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 会自动检测到代码变化,无需手动重启服务,直接加载新代码
装饰器
下面通过一个简单的“加法计算”示例,直观展示有无装饰器的区别。示例中,装饰器用于统一添加“日志记录”和“参数校验”功能
场景说明:
实现一个“加法计算”功能,需要:
- 记录每次计算的日志(输入参数、结果);
- 校验输入参数是否为数字(非数字则提示错误)。
一、无装饰器的实现(传统方式)
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
问题分析:
- 代码冗余:如果有多个函数(如
subtract
、multiply
),每个函数都要重复写“参数校验”和“日志记录”代码; - 维护困难:若要修改日志格式或校验规则,需逐个修改所有函数。
二、有装饰器的实现(优化方式)
将“日志记录”和“参数校验”封装成装饰器,实现逻辑复用:
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 resultreturn 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
修饰,自动获得相同的校验和日志功能:@log_and_validate def subtract(a, b):return a - b # 无需重复写校验和日志
-
易于维护:修改日志格式或校验规则时,只需修改
log_and_validate
装饰器,所有被修饰的函数都会生效。