You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flask路由间持久化非JSON可序列化的BLE连接对象

解决Flask路由间持久化非序列化BLE连接对象的问题

首先看你代码里的几个核心问题:

  • 缓存键名大小写不一致:ConnectUUT里用cache.set("BLEComm", BLEComm)存储对象,DisconnectUUT里却用cache.get("ble_comm")读取,大小写不匹配直接导致取不到实例。
  • SimpleCache是进程内缓存,若服务器启用多进程模式(比如Waitress默认可能配置多进程),不同进程的缓存完全隔离,对象无法跨进程共享。
  • 代码中未从请求参数中获取MAC_ID,直接调用会触发未定义变量错误。

针对非JSON可序列化对象的跨路由持久化,推荐以下几种可靠方案:

方案1:将实例绑定到Flask App全局对象

Flask的app对象是全局共享的,直接把BLE连接实例挂载到app上,彻底规避缓存的序列化和跨进程隔离问题。

修改后的代码:

from flask import Flask, request
from waitress import serve
from clsBLEcomm import clsBLEcomm

app = Flask(__name__)

# 初始化BLE连接实例到app全局属性
app.ble_comm = clsBLEcomm()

@app.route('/api/ConnectUUT', methods=['get'])
async def ConnectUUT():
    ErrorResponse = '0: OK'
    mac_id = request.args.get('MAC_ID')
    if not mac_id:
        return '1: Missing MAC_ID parameter', 400
    
    await app.ble_comm.ConnectUUT(MAC_ID=mac_id)
    return ErrorResponse

@app.route('/api/DisconnectUUT', methods=['get'])
async def DisconnectUUT():
    ErrorResponse = '0: OK'
    await app.ble_comm.DisconnectUUT()
    return ErrorResponse

if __name__ == '__main__':
    serve(app, port=5000)

方案2:用单例模式实现BLE通信类

让clsBLEcomm本身成为单例,无论在哪调用clsBLEcomm()都会返回同一个实例,从根源解决实例共享问题。

修改clsBLEcomm.py:

class clsBLEcomm:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

    # 原有连接逻辑
    async def ConnectUUT(self, MAC_ID):
        # 你的BLE连接实现
        pass

    # 原有断开逻辑
    async def DisconnectUUT(self):
        # 你的BLE断开实现
        pass

对应Flask代码简化为:

from flask import Flask, request
from waitress import serve
from clsBLEcomm import clsBLEcomm

app = Flask(__name__)

@app.route('/api/ConnectUUT', methods=['get'])
async def ConnectUUT():
    ErrorResponse = '0: OK'
    mac_id = request.args.get('MAC_ID')
    if not mac_id:
        return '1: Missing MAC_ID parameter', 400
    
    ble_comm = clsBLEcomm()
    await ble_comm.ConnectUUT(MAC_ID=mac_id)
    return ErrorResponse

@app.route('/api/DisconnectUUT', methods=['get'])
async def DisconnectUUT():
    ErrorResponse = '0: OK'
    ble_comm = clsBLEcomm()
    await ble_comm.DisconnectUUT()
    return ErrorResponse

if __name__ == '__main__':
    serve(app, port=5000)

方案3:修正缓存用法(仅适合同进程服务器)

如果坚持用Flask-Caching,先修正键名问题,同时强制服务器使用单进程模式:

修改后的缓存版代码:

from flask import Flask, request
from flask_caching import Cache
from waitress import serve
from clsBLEcomm import clsBLEcomm

config = {
    "DEBUG": True,
    "CACHE_TYPE": "SimpleCache",
    "CACHE_DEFAULT_TIMEOUT": 300 
}

app = Flask(__name__)
app.config.from_mapping(config)
cache = Cache(app)

@app.route('/api/ConnectUUT', methods=['get'])
async def ConnectUUT():
    ErrorResponse = '0: OK'
    mac_id = request.args.get('MAC_ID')
    if not mac_id:
        return '1: Missing MAC_ID parameter', 400
    
    # 统一使用小写键名
    BLEComm = cache.get("ble_comm_instance")
    if BLEComm is None:
        BLEComm = clsBLEcomm()
        cache.set("ble_comm_instance", BLEComm)
    
    await BLEComm.ConnectUUT(MAC_ID=mac_id)
    return ErrorResponse

@app.route('/api/DisconnectUUT', methods=['get'])
async def DisconnectUUT():
    ErrorResponse = '0: OK'
    # 用相同键名读取实例
    BLEComm = cache.get("ble_comm_instance")
    if BLEComm is None:
        return '1: No active BLE connection', 400
    
    await BLEComm.DisconnectUUT()
    # 断开后清除缓存中的实例
    cache.delete("ble_comm_instance")
    return ErrorResponse

if __name__ == '__main__':
    # 指定Waitress用单进程,避免多进程缓存隔离
    serve(app, port=5000, threads=4, processes=1)

注意:若服务器启用多进程模式,SimpleCache无法跨进程共享对象,此时方案1或方案2是更可靠的选择。

内容的提问来源于stack exchange,提问作者Hamilton Woods

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:47:05