我正在使用以下代码与数字万用表(DMM)通信。
工作正常。我可以发送命令和读取结果。
我不使用readline,因为我读取二进制数据。
问题:
问题是它非常慢。
用Ruby编写同样的代码要快得多。
在python中需要30秒,在ruby中需要2到3秒(使用相同的速度)。
所以这不是硬件问题。
Ruby代码和Python的唯一区别是,在Python中,我使用inWaiting()读取所有可用的字符。在Ruby中,read()函数会读取所有这些内容,而不仅仅是一个。
代码:
代码如下:
在read_retry函数中,我检查需要读取的字符数。
我读了它们,然后调用data is ok函数来检查它是否完成。
如您所见,返回的数据中嵌入了'\r'。
当最后一个字符为'\r'(没有更多可用数据)时,读取完成。
所以有一个循环来读取许多块。import serial
[...]
def data_is_ok(data):
# No status code yet
if len(data) < 2: return False
# Non-OK status
if len(data) == 2 and data[0] != "0" and data[1] == "\r": return True
# Non-OK status with extra data on end
if len(data) > 2 and data[0] != "0":
raise ValueError('Error parsing status from meter (Non-OK status with extra data on end)')
# We should now be in OK state
if data[0] != "0" or data[1] != "\r":
raise ValueError('Error parsing status from meter (status:%c size:%d)' % (data[0], len(data)))
return len(data) >= 4 and data[-1] == "\r"
def read_retry():
retry_count = 0
data = ""
while retry_count < 500 and not data_is_ok(data):
bytesToRead = ser.inWaiting()
data += ser.read(bytesToRead)
if data_is_ok(data): return data
time.sleep (0.001)
retry_count += 1
raise ValueError('Error parsing status from meter: %c %d %r %r' % (data[0],len(data),data[1] == '\r', data[-1] == '\r'))
[...]
# Serial port settings
try:
ser = serial.Serial(port='/dev/cu.usbserial-AK05FTGH', baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=5, rtscts=False, dsrdtr=False)
except serial.serialutil.SerialException, err:
print "Serial Port /dev/cu.usbserial-AK05FTGH doesn't respond"
print err
sys.exit()
[...]
ser.write(cmd+'\r')
data = read_retry()
我用过cProfile轮廓仪。大部分时间都花在时间上
以下是摘录:363096 function calls (363085 primitive calls) in 28.821 seconds
Ordered by: internal time
List reduced from 127 to 10 due to restriction <10>
ncalls tottime percall cumtime percall filename:lineno(function)
19050 25.245 0.001 25.245 0.001 {time.sleep}
1 1.502 1.502 1.502 1.502 {posix.open}
问题是:
是否可以使代码更快?