You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python Flask串口服务程序无法访问COM3端口(权限拒绝)求助

Python Flask串口服务程序无法访问COM3端口(权限拒绝)求助

问题描述

我开发了一个基于Flask的Python程序,用来通过Web接口操作COM3串口:接收Web请求后向串口发送数据,或者读取串口数据返回给请求方。代码在我的个人笔记本上能正常运行,但部署到工作电脑时,启动程序就抛出权限拒绝的错误:

serial.serialutil.SerialException: could not open port 'COM3': PermissionError(13, 'Access is denied.', None, 5)

我已经做了这些排查:

  1. 用管理员权限启动终端运行脚本;
  2. serial.tools.list_ports能正常检测到COM3端口;
  3. 确认没有其他程序占用该串口。

我的完整代码如下:

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,提问作者Тарас Гаврилюк

火山引擎 最新活动