Python readlines Api从串口访问时需要很长时间

Posted

技术标签:

【中文标题】Python readlines Api从串口访问时需要很长时间【英文标题】:Python readlines Api takes long time while accessing from serial port 【发布时间】:2015-07-07 15:45:56 【问题描述】:

我有 12 个串行设备连接到我的 PC,要从设备中读取一个值大约需要 4 秒,而下面的 sn-p 总共需要大约 1 分钟来读取所有值。他们是一种优化以下 python 脚本或使用其他 API 的方法,这可以花费更少的时间来串行访问设备和读取值

代码片段:

if sys.platform.startswith('linux'):
        for sfiles in glob.glob('/dev/serial/by-id/usb-XXXXdevNAME*'):
            try:
                s = serial.Serial(sfiles, 9600, timeout=2)
                s.write('XXXdeviceCommandToReadValue XXXX\r\n')
                response = s.readlines() // from the profiles it looks readlines is using more time 

Profiler 结果:

    16309 function calls (16306 primitive calls) in 54.605 seconds Ordered by: cumulative time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.001    0.001   54.605   54.605 /opt/lnx_attenTool/att_devices.py:49(scan_devices)
   12    0.009    0.001   54.522    4.543 method 'readlines' of '_io._IOBase' objects
 2136    0.020    0.000   54.513    0.026 /usr/lib/python2.7/dist-packages/serial/serialposix.py:439(read)
 2136   54.482    0.026   54.482    0.026 select.select
   24    0.000    0.000    0.072    0.003 /usr/lib/python2.7/dist-packages/serial/serialposix.py:419(close)
   12    0.072    0.006    0.072    0.006 posix.close
 2112    0.007    0.000    0.007    0.000 posix.read
   12    0.001    0.000    0.007    0.001 /usr/lib/python2.7/dist-packages/serial/serialutil.py:213(__init__)
   12    0.000    0.000    0.005    0.000 /usr/lib/python2.7/dist-packages/serial/serialposix.py:265(open)
   12    0.004    0.000    0.004    0.000 posix.open
 2112    0.002    0.000    0.002    0.000 method 'extend' of 'bytearray' objects
    1    0.000    0.000    0.002    0.002   /usr/lib/python2.7/glob.py:18(glob)
   13    0.000    0.000    0.002    0.000 /usr/lib/python2.7/glob.py:29(iglob) 
   6523/6522    0.002    0.000    0.002    0.000 len
    1    0.000    0.000    0.002    0.002 /usr/lib/python2.7/glob.py:66(glob1)
    1    0.000    0.000    0.001    0.001 /usr/lib/python2.7/fnmatch.py:45(filter)
   12    0.001    0.000    0.001    0.000 /usr/lib/python2.7/dist-packages/serial/serialposix.py:297(_reconfigurePort)
    1    0.000    0.000    0.001    0.001 /usr/lib/python2.7/re.py:188(compile)
    1    0.000    0.000    0.001    0.001 /usr/lib/python2.7/re.py:226(_compile)
    1    0.000    0.000    0.001    0.001 /usr/lib/python2.7/sre_compile.py:493(compile)
    1    0.000    0.000    0.001    0.001 /usr/lib/python2.7/sre_parse.py:675(parse)
    1    0.000    0.000    0.001    0.001 /usr/lib/python2.7/sre_parse.py:301(_parse_sub)
    1    0.000    0.000    0.001    0.001 /usr/lib/python2.7/sre_parse.py:379(_parse)
   12    0.000    0.000    0.000    0.000 /usr/lib/python2.7/dist-packages/serial/serialposix.py:464(write)
    1    0.000    0.000    0.000    0.000 /usr/lib/python2.7/sre_compile.py:478(_code)
      12    0.000    0.000    0.000    0.000 posix.readlink

谢谢, 罗希特

【问题讨论】:

你分析过这段代码吗?你确定这就是减速的地方吗?我有一种感觉,读/写文件操作是减速的地方,而不是从设备中获取价值。 不,我没有进行分析,也不确定读/写操作。但是在使用腻子时,我没有看到发出设备命令的任何延迟 好吧,我建议看看this 来确定减速而不是仅仅猜测。 这是分析器结果:ncalls tottime percall cumtime percall filename:lineno(function) 1 0.001 0.001 54.605 54.605 /opt/lnx_attenTool/att_devices.py:49(scan_devices) 12 0.009 0.001 54.522 4.543 meth '_io._IOBase' 对象的'readlines' 2136 0.020 0.000 54.513 0.026 /usr/lib/python2.7/dist-packages/serial/serialposix.py:439(读取) 我投票结束这个问题,因为它应该被迁移到Code Review 【参考方案1】:

如果设备是独立的;您可以同时阅读他们的回复:

#!/usr/bin/env python
from glob import glob
from multiprocessing.pool import ThreadPool
import serial

def get_response(path):
    try:
        s = serial.Serial(path, 9600, timeout=2)
        s.write('XXXdeviceCommandToReadValue XXXX\r\n')
        return path, s.readlines(), None
    except Exception as e:
        return path, None, e

paths = glob('/dev/serial/by-id/usb-XXXXdevNAME*')
results = ThreadPool(min(len(paths), 20)).imap_unordered(get_response, paths)
for path, lines, error in results:
    print(path, lines, error) # handle results here

假设大部分时间都花在 I/O 上,代码应该会更快完成。

此外,请调查s.readlines() 在这种情况下是否是正确的 API 用法(在它之前是否需要 s.flush()?您应该读取单行还是固定数量的字节?)。对于普通文件/管道,.readlines() 将读取所有数据,直到 EOF。检查它是否对串行设备有意义。

【讨论】:

以上是关于Python readlines Api从串口访问时需要很长时间的主要内容,如果未能解决你的问题,请参考以下文章

Pyserial操作串口

Python对microbit串口拒绝访问

python的串口close()函数关闭不成功

python3.6如何向串口发送Android adb命令,求大神指点

K210实战三-串口收发实验

K210实战三-串口收发实验