Python pyserial 和 CPU 占用过高

0 投票
3 回答
1277 浏览
提问于 2025-04-17 12:42

我在用MacOS 10.7.3和python 2.5,使用pyserial来连接一个外部服务器。连接的方式是这样的:

HOST = '10.0.0.1'
PORT = '16010'
theURL = 'socket://' + HOST + ':' + PORT
conn = serial.serial_for_url(theURL, baudrate=115200)
conn.timeout = 2

然后读取数据的代码是这样的:

try:
    while len(rawData) == 0 and self.shutdown == False:
        rawData = conn.readline()
except:
    some error handling code...

问题是,如果我把10.0.0.1:16010上的服务器关掉,代码还是会继续运行,但CPU的使用率会飙到100%。没有出现错误,所以也不会进入异常处理的部分。

这看起来像是pyserial的问题,但也许这里有人遇到过类似的情况,知道怎么检测到连接丢失,这样就能优雅地处理这个问题。

谢谢。

3 个回答

0

一个很好的解决方案可以在这里找到:

class ReadLine:
    def __init__(self, s):
        self.buf = bytearray()
        self.s = s

    def readline(self):
        i = self.buf.find(b"\n")
        if i >= 0:
            r = self.buf[:i+1]
            self.buf = self.buf[i+1:]
            return r
        while True:
            i = max(1, min(2048, self.s.in_waiting))
            data = self.s.read(i)
            i = data.find(b"\n")
            if i >= 0:
                r = self.buf + data[:i+1]
                self.buf[0:] = data[i+1:]
                return r
            else:
                self.buf.extend(data)

ser = serial.Serial('COM7', 9600)
rl = ReadLine(ser)

while True:

    print(rl.readline())
0

你的CPU使用率一直很高,这可能说明readline这个调用没有像预期那样等待超时,而是立刻返回了结果。所以如果你正常的超时时间是2秒,你可以使用:

from time import time

try:
    while len(rawData) == 0 and self.shutdown == False:
        before = time()  
        rawData = conn.readline()
        if (len(rawData)==0) and ((time()-before)<2):
              raise Exception("Early readline return.")
except:
    some error handling code...
0

如果你不依赖于 .readline() 这个方法,你可以这样做:

self.plugin.conn = Serial(..., timeout = 1)
...
if not self.shutdown:
    rawData = self.plugin.conn.read(1)
    if rawData:
        rawData += self.plugin.conn.read(self.plugin.conn.inWaiting())
    else:
        raise Exception("timeout")

我不太确定我是否理解了你的意思,所以你可能需要进行一些调整...

撰写回答