简体   繁体   English

Python pyserial和失控的CPU使用率

[英]Python pyserial and runaway CPU usage

MacOS 10.7.3, python 2.5 MacOS 10.7.3,Python 2.5

I am using pyserial to open a connection to an external server. 我正在使用pyserial打开与外部服务器的连接。 The connection is opened as: 连接打开为:

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

and then the read looks like this: 然后读取如下所示:

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

The problem is, if I kill the server at 10.0.0.1:16010 the code keeps running, but the cpu usage goes to 100%. 问题是,如果我在10.0.0.1:16010处杀死服务器,则代码将继续运行,但CPU使用率将达到100%。 No error is thrown, so the except is never entered. 没有引发错误,因此永远不会输入除外。

This looks like a problem in pyserial, but maybe someone here has run into this before and knows how to detect the lost connection so the situation can be handled gracefully. 这在pyserial中似乎是一个问题,但是也许有人在此之前遇到过这种情况,并且知道如何检测丢失的连接,以便可以妥善处理此情况。

Thanks. 谢谢。

The fact that your CPU usage is pegged probably indicates the the readline call is not blocking to timeout but returns instantly. 与CPU使用率挂钩的事实可能表明readline调用并未阻塞超时,而是立即返回。 So if your normal timeout is 2, you could use: 因此,如果您的正常超时时间是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...

A very good solution to this can be found here : 一个很好的解决方案可以在这里找到:

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())

If you're not depending on .readline() you could do it like this: 如果您不依赖于.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")

I'm not sure if I got your intent right so you might have to adjust... 我不确定我的意图是否正确,因此您可能需要调整...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM