Flask集成pyserial打开COM7端口报错SerialException问题咨询
问题排查与解决方案
核心原因
- Flask debug模式默认开启重载器:
debug=True时Flask会启动2个进程(主进程+代码热重载进程),串口属于系统独占资源,第一个进程占用COM7后,第二个进程再尝试打开就会抛出端口占用异常,这是最核心的触发原因。 - 串口初始化逻辑错误:你将
serial.Serial实例化放在了serial_start函数内,且该函数被绑定到/路由的处理逻辑中,每次访问/路径都会重新尝试打开一次已经被占用的串口,也会触发报错。 - 串口监听逻辑阻塞服务:
serial_start内部是死循环,直接放在Flask请求处理函数中会永久阻塞当前请求,甚至拖垮整个Web服务的响应能力。
对应解决方案
- 关闭Flask重载器或者禁用debug模式:启动服务时添加
use_reloader=False参数,避免多进程重复抢占串口。 - 全局初始化串口:将串口实例放在全局位置,确保服务生命周期内只打开一次串口。
- 用独立后台线程运行串口监听逻辑:不要占用Flask的请求处理线程运行死循环监听任务。
修正后可运行代码
from flask import Flask, request, render_template, Response import serial import threading main = Flask(__name__) # 全局初始化串口,仅执行一次 ser = serial.Serial('com7', 9600) stop_flag = False def serial_start(): while not stop_flag: if ser.readable(): res = ser.readline() res_decode = res.decode().strip() print(res_decode) @main.route('/') def hello_fnc(): return 'Hello' @main.route('/page', methods = ["GET", "POST"]) def page_fnc(): if request.method == "POST": return 'POST received' else: return render_template("index.htm") if __name__ == '__main__': # 启动串口监听后台线程 serial_thread = threading.Thread(target=serial_start, daemon=True) serial_thread.start() # 关闭重载器,避免多进程抢占串口 main.run(debug=True, use_reloader=False)
内容的提问来源于stack exchange,提问作者Dongju
相关产品推荐
相关产品推荐

