如何让Flask Blueprint下的各应用分端口运行并解决请求阻塞?
问题根源分析
你猜的完全没错!问题就出在Flask默认的单线程开发服务器上。当你的网站路由(/)发起HTTP请求到同端口的API时,服务器正被当前的网站请求占着,根本腾不出手处理新的API请求,直接陷入了无限等待的死锁状态——这也是为什么POSTMAN能正常调用API(它是外部独立请求,服务器空闲时就能处理),但网站内部调用却卡得一动不动。
解决方案(按推荐优先级排序)
1. 直接调用API函数(最优方案,无HTTP开销)
既然网站和API本来就是同一个Flask应用里的模块,完全没必要绕HTTP请求的弯路,直接调用API的视图函数就行。唯一需要注意的是,Flask的request对象依赖请求上下文,所以我们得手动模拟一下这个环境:
修改你的网站调用代码:
from flask import current_app, request from your_api_blueprint_file import mod as api_mod # 替换成你实际的API Blueprint导入路径 mod = Blueprint('site', __name__, template_folder='templates/login') def load_user(username, password): # 模拟请求上下文,构造API需要的authorization对象 with current_app.test_request_context(): # 造个和request.authorization结构一致的模拟类 class MockAuthorization: def __init__(self, username, password): self.username = username self.password = password request.authorization = MockAuthorization(username, password) # 直接调用API的login视图函数 api_response = api_mod.view_functions['login']() # 提取返回的JSON数据 return api_response.get_json() @mod.route('/') def index(): username = 'jeje' password = 'jeje' data = load_user(username, password) return f'<h1>Loaded user data: {data}</h1>'
这种方式既省了HTTP请求的开销,还能完全共享应用内的所有对象和工具,完全不用重复写代码。
2. 启用Flask开发服务器的多线程/多进程模式
如果你非要保留HTTP调用的方式(比如想提前模拟生产环境的调用逻辑),可以在启动Flask应用时开启多线程或多进程,让服务器能同时处理多个请求:
if __name__ == '__main__': # 多线程模式,适合IO密集型任务 app.run(threaded=True) # 或者多进程模式,适合CPU密集型场景 # app.run(processes=2)
不过这种方式会有额外的HTTP开销,而且开发环境下多线程/进程可能会出现上下文缓存、数据库连接之类的小问题,只适合作为过渡方案用。
3. 拆分应用但共享核心代码(适合未来独立部署)
如果以后需要把API和网站拆成独立服务部署,可以提前把共享的核心代码抽离出来,避免重复开发:
- 创建
core目录,放所有共享内容:models.py:USER数据库模型utils.py:validehash、createtoken这类工具函数config.py:SECRET_KEY这类共享配置
- API应用:导入
core模块,创建独立的Flask实例和Blueprint,监听端口5000 - 网站应用:同样导入
core模块,创建独立的Flask实例和Blueprint,监听端口5001
这样拆分后,两个服务完全独立,但核心逻辑只需要维护一份,完美满足你“不重复开发”的需求。
内容的提问来源于stack exchange,提问作者Jerome




