Python Flask串口服务程序无法访问COM3端口(权限拒绝)求助
问题描述
我开发了一个基于Flask的Python程序,用来通过Web接口操作COM3串口:接收Web请求后向串口发送数据,或者读取串口数据返回给请求方。代码在我的个人笔记本上能正常运行,但部署到工作电脑时,启动程序就抛出权限拒绝的错误:
serial.serialutil.SerialException: could not open port 'COM3': PermissionError(13, 'Access is denied.', None, 5)
我已经做了这些排查:
- 用管理员权限启动终端运行脚本;
- 用
serial.tools.list_ports能正常检测到COM3端口; - 确认没有其他程序占用该串口。
我的完整代码如下:
from flask import Flask, request, jsonify import serial app = Flask(__name__) ser = serial.Serial('COM3', 9600, timeout=1) @app.route('/send', methods=['POST']) def send(): data = request.get_json().get('data', '') if data: write_to_port(ser, data) response = read_full_response(ser) return jsonify({"message": response}), 200 else: return jsonify({"error": "No data provided"}), 400 @app.route('/read', methods=['GET']) def read(): reading = read_from_port(ser) return jsonify({"message": reading}), 200 def read_from_port(ser): reading = ser.readline().decode('utf-8').strip() print('Read:', reading) return reading def write_to_port(ser, data): ser.write(data.encode()) print(f"Written: {data}") def read_full_response(ser): response = b"" while True: if ser.in_waiting: chunk = ser.read(ser.in_waiting) response += chunk if b"\x00" in chunk: break return response.decode('utf-8').strip() if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000)
请问还有什么可能的原因会导致这个权限问题?
排查与解决办法
这种明明端口存在、也用了管理员权限但还是报错的情况,大概率是系统级的权限限制或者隐性资源占用,我给你几个实用的排查方向:
检查串口设备的系统权限设置
打开Windows设备管理器,找到「端口(COM和LPT)」下的COM3设备,右键→属性→安全标签,查看当前管理员用户组是否拥有「读取/写入」的权限。如果没有,点击「编辑」添加权限并保存,然后重新运行程序。彻底释放串口资源
有时候程序崩溃或者异常退出后,串口资源可能没有被系统正常释放,即使任务管理器里看不到相关进程。你可以:- 直接重启工作电脑,这是最彻底的释放方式;
- 用第三方串口工具(比如Putty、SSCOM)尝试手动打开COM3,如果工具也报错,说明是串口本身的问题,不是代码的问题。
确认Python进程的实际权限
虽然你用管理员终端启动了脚本,但如果使用了虚拟环境,虚拟环境中的Python进程可能没有正确继承管理员权限。可以试试:- 右键以管理员身份打开命令提示符,先激活虚拟环境(如果用了的话),再运行你的脚本;
- 或者直接在管理员终端里运行系统自带的Python解释器(而非虚拟环境的)来执行脚本,排除虚拟环境的权限问题。
排查安全软件的拦截
企业级的杀毒软件、EDR(终端检测与响应)或者防火墙,经常会拦截对硬件端口的访问,哪怕是管理员权限也不例外。你可以临时关闭这些安全软件,再运行脚本试试,如果能正常工作,就需要在安全软件中添加Python进程或你的脚本的白名单。检查串口驱动与参数匹配
工作电脑的串口设备可能和你的笔记本型号不同,需要特定的驱动或串口参数:- 卸载当前串口驱动,到设备厂商官网下载最新版本重新安装;
- 在代码中打开串口时,补充完整的串口参数(比如奇偶校验、停止位),确保和设备要求一致:
import serial ser = serial.Serial( port='COM3', baudrate=9600, timeout=1, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_1, bytesize=serial.EIGHTBITS, exclusive=True # 启用独占访问,需要pyserial 3.4+ )
尝试延迟打开串口
有时候系统启动后串口设备还没完全初始化,代码里在程序启动时就打开串口会失败。你可以把串口初始化放在Flask的请求处理函数里,或者添加延迟:import time app = Flask(__name__) ser = None @app.before_first_request def init_serial(): global ser time.sleep(2) # 延迟2秒等待设备初始化 ser = serial.Serial('COM3', 9600, timeout=1)
备注:内容来源于stack exchange,提问作者Тарас Гаврилюк




