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

使用pymodbus时如何阻止其他程序占用正在使用的COM端口?

解决COM端口被其他程序抢占的问题

核心思路

串口(COM端口)本身是独占式硬件资源,但部分系统或程序可能未正确检测端口占用状态。要阻止其他程序抢占,需从客户端连接保持、系统级独占配置、应用层互斥锁三个层面入手。


1. 保持客户端持续连接锁定端口

pymodbus的ModbusClient在调用connect()后会默认保持串口打开,只要不主动关闭,系统会标记端口为已占用。避免频繁断开重连是关键:

import time
from pymodbus.client import ModbusClient

client = ModbusClient(method='rtu', port=port, stopbits=2, bytesize=8, parity='N', baudrate=19200, timeout=1)
if client.connect():
    try:
        # 持续读取数据的循环,保持连接状态
        while True:
            response = client.read_holding_registers(address=0, count=10, unit=1)
            # 处理读取到的数据
            print(response.registers if not response.isError() else response)
            time.sleep(1)
    except Exception as e:
        print(f"读取异常: {str(e)}")
    finally:
        client.close()
else:
    print(f"无法连接到端口 {port}")

2. Windows系统启用串口独占模式

Windows系统支持串口独占访问配置,通过pyserial底层对象设置exclusive=True,其他程序尝试打开端口时会直接报错:

import serial
from pymodbus.client import ModbusSerialClient

# 先创建串口对象并启用独占模式
ser = serial.Serial(port=port, baudrate=19200, bytesize=8, parity='N', stopbits=2, timeout=1)
ser.exclusive = True  # 仅Windows系统支持

# 用配置好的串口对象初始化Modbus客户端
client = ModbusSerialClient(method='rtu', serial_instance=ser)
if client.connect():
    # 后续读取逻辑同示例1
    pass

3. Linux/macOS应用层文件锁互斥

在类Unix系统中,可通过文件锁实现应用级端口互斥,其他程序检测到锁文件则不再尝试连接:

import fcntl
import os
from pymodbus.client import ModbusClient

# 生成对应端口的锁文件路径
lock_file = f"/tmp/serial_lock_{port.replace('/', '_')}"
lock_fd = open(lock_file, 'w')

try:
    # 尝试获取独占锁,非阻塞模式
    fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
    
    # 锁成功,初始化客户端
    client = ModbusClient(method='rtu', port=port, stopbits=2, bytesize=8, parity='N', baudrate=19200, timeout=1)
    if client.connect():
        # 读取逻辑
        pass
except BlockingIOError:
    print(f"端口 {port} 已被锁定,无法重复连接")
finally:
    # 程序退出时释放锁并删除锁文件
    fcntl.flock(lock_fd, fcntl.LOCK_UN)
    lock_fd.close()
    os.unlink(lock_file)

4. 端口占用预检测

程序启动前先检查端口是否被占用,提前规避冲突:

import serial.tools.list_ports

def is_port_occupied(port):
    for p in serial.tools.list_ports.comports():
        if p.device == port:
            return True
    return False

if is_port_occupied(port):
    print(f"端口 {port} 已被其他程序占用")
else:
    # 初始化客户端并执行读取逻辑
    pass

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 14:35:15