Flask RESTful服务调用Linear SVC文本分类模型报错求助
让我们一步步拆解问题,找到导致JSONDecodeError的根源并逐一修复:
1. 核心原因:Flask路由未开放POST请求权限
你的Flask根路由@app.route("/")默认只接受GET请求,当你用POST方法发送请求时,Flask会返回405 Method Not Allowed的非JSON响应,这直接导致客户端解析JSON时报错。
修复方案:给路由明确添加methods=['POST']参数:
@app.route("/", methods=['POST']) # 新增methods参数,允许POST请求 def make_predict(): # 后续代码逻辑保持(先改这里,再处理其他问题)
2. 端口不匹配:客户端请求的端口与服务端不一致
你的Flask服务启动在默认的5000端口(启动时显示http://localhost:5000/),但客户端代码里请求的是8082端口:
url = "http://localhost:8082/"
这会导致请求根本没到达你的API,返回的是无法连接的错误页面,自然无法解析为JSON。
修复方案:把客户端的url改成服务端的实际端口:
url = "http://localhost:5000/"
3. Flask代码中的数组创建语法错误
你这里用了方括号np.array[predict_request],这是错误的语法——创建numpy数组应该用圆括号,同时还要给文本加一层列表包装(因为LinearSVC.predict()要求输入是二维数组):
# 错误写法 predict_request = np.array[predict_request] # 正确写法 predict_request = np.array([predict_request]) # 加一层列表,转成模型需要的二维输入格式
4. 客户端结果提取的键名不匹配
服务端返回的是jsonify(results=output),但客户端代码里尝试提取['Output']:
Output = json.loads(r.text)['Output']
这会导致KeyError,应该改成对应服务端的键名results:
Output = json.loads(r.text)['results']
5. 额外优化:简化客户端请求代码
requests库支持直接传入json参数,不需要手动json.dumps,它会自动设置正确的Content-Type请求头,代码更简洁:
import requests url = "http://localhost:5000/" data = {'Clean_Text_Body':"the product was amazing i just love it"} # 直接用json参数,无需手动序列化和设置headers r = requests.post(url, json=data) Output = json.loads(r.text)['results'] print("results == ", Output)
修正后的完整Flask代码
import numpy as np import pandas as pd from flask import Flask, abort, jsonify, request import pickle # 加载模型(确保路径正确) Text_classification_model = pickle.load(open(r"D:\Sentiment_Analysis_Project\Deb\Sentiment_Analysis\Linear_SVC_TEXT_CLASSI_Final_82per_Model.pkl", "rb")) app = Flask(__name__) @app.route("/", methods=['POST']) # 允许POST请求 def make_predict(): try: # 解析请求JSON data = request.get_json(force=True) predict_request = data['Clean_Text_Body'] # 转换为模型需要的二维数组格式 predict_request = np.array([predict_request]) # 模型预测 y_hat = Text_classification_model.predict(predict_request) # 返回结果(转成列表更符合JSON格式) return jsonify(results=y_hat.tolist()) except Exception as e: # 捕获异常并返回错误信息,方便调试 abort(400, description=str(e)) if __name__ == '__main__': app.run(debug=True) # 开启debug模式,方便查看错误详情
最后补充一个注意点:确保你的LinearSVC模型是包含特征提取步骤的(比如和TF-IDF Vectorizer打包成了Pipeline)。如果模型只是单独的分类器,直接传入原始文本字符串会报错——因为模型需要的是数值化的特征向量,而不是文本。如果是这种情况,你需要把特征提取器和模型一起保存为Pipeline,再加载使用。
内容的提问来源于stack exchange,提问作者Deb

