问题描述
几年来,我一直非常愉快地在基于Windows(10)的Python脚本中使用PySerial(3.4)与嵌入式目标通信。随着即将淘汰的Python 2,我最近将所有Python 2.7.15脚本都移至了Python 3,决定直接使用Python 3.8.5。但是,我遇到了在Python 3.8.5上运行时PySerial read()
似乎有问题的问题。
场景:
我有目标硬件,该硬件将输出流传输到由脚本在115,200读取的COM端口,没有流控制。我知道目标的表现是因为我可以看到我的脚本的Python 2.7.15版本可以连续读取它,没有延迟/延迟,而且我也可以在PuTTY中看到它。输出由以“ \ r \ n”结尾的所有ASCII文本行组成,所有这些流一起传输。但是,在Python 3.8.5(PySerial 3.4)下,read(1)
花费大约30毫秒返回每个字符(通过将time()
调用前后的read(1)
之间的差异转储到列表中来测量) ),因此接收30个字符大约需要1秒。是的,我知道单个字符的读取效率不高,但肯定不是 this 效率低;我想控制行尾的搜索,并且由于该字符已经存在于Windows缓冲区中,因此它应该很快返回(在Python 2中也是如此)。
还有其他人看到过这种性质的问题吗?当然,这可能与Python 3的线程行为有关。我可以尝试使用其他版本的Python 3,但我要移动的Python脚本结构相对较大,因此需要进行一次有价值的下注。我在PySerial上提出了一个问题,但我担心它可能不会再得到积极维护。
编辑:如果我将read(1)
从其线程中取出,则它的运行速度与在Python 2.7上的运行速度相同,因此问题与PySerial无关,这与线程中的更改方式有关。 Python 3。
详细信息: 我打开串口如下:
in_handle = serial.Serial("COM8",115200,timeout=0.05)
...然后我有一个在线程中运行的函数,该线程读取in_handle
如下:
terminator = "\r"
line = ""
eol = False
return_value = None
try:
while not eol and line is not None:
buf = in_handle.read(1)
if buf:
character = buf.decode('ascii')
eol = character == terminator
if not eol:
line = line + character
else:
line = None
if eol:
line = line.strip()
except UnicodeDecodeError:
# Just ignore it.
pass
return_value = line
此操作的输出放在队列中:
read_queue.put(return_value)
...并且主线程创建队列/串行读取线程,并使用以下命令从队列中取出内容:
read_queue = queue.Queue()
readline_thread = threading.Thread(target=readline_and_queue,args=(in_handle))
readline_thread.start()
while True:
try:
line = read_queue.get(block=False,timeout=0.5)
# do something with the result
except queue.Empty:
pass
当我在time()
调用的任一侧使用read(1)
来测量其持续时间时,对于一行34个字符的行,我得到的值是:
0.03198051452636719
0.031983137130737305
0.031981468200683594
0.0159909725189209
0.031981706619262695
0.0319819450378418
0.0479733943939209
0.031982421875
0.0319826602935791
0.03198075294494629
0.031982421875
0.0319819450378418
0.0319826602935791
0.0159912109375
0.0159909725189209
0.03198122978210449
0.0319819450378418
0.0319821834564209
0.0319821834564209
0.0319821834564209
0.030982255935668945
0.03098273277282715
0.031981706619262695
0.0319826602935791
0.0319821834564209
0.031981706619262695
0.0319819450378418
0.0319819450378418
0.0319821834564209
0.0319828987121582
0.03198075294494629
0.031983375549316406
0.031981468200683594
0.0319821834564209
解决方法
修复了它,这是我自己的愚蠢错误:由于我现在不记得的原因,我使出队成为非阻塞的,所以Python毫无意义地破坏了该循环。问题是,为什么魔鬼在Python 2中不是一个问题?