python - PySerial 非阻塞读取循环

标签 python python-3.x nonblocking pyserial

我正在读取这样的串行数据:

connected = False
port = 'COM4'
baud = 9600

ser = serial.Serial(port, baud, timeout=0)

while not connected:
    #serin = ser.read()
    connected = True

    while True:
        print("test")
        reading = ser.readline().decode()

问题在于它阻止了其他任何东西的执行,包括bottle py web框架。添加 sleep() 不会有帮助。

将 "while True""更改为 "while ser.readline():"不会打印 "test",这很奇怪,因为它在 Python 2.7 中有效。有什么想法可能是错误的吗?

理想情况下,我应该只有在可用时才能读取串行数据。每 1000 毫秒发送一次数据。

最佳答案

完全没有必要使用单独的线程。只需按照下面的示例进行无限 while 循环即可。

我在我的 eRCaGuy_PyTerm 串行终端程序 here (search the code for inWaiting() or in_waiting) 中使用了这种技术

注意事项:

  1. 要检查你的 python3 版本,运行这个:

    python3 --version
    

    当我第一次编写和测试这个答案时,我的输出是 Python 3.2.3

  2. 要检查你的 pyserial 库(serial 模块)版本,运行这个——我第一次学习这个 here :

    python3 -c 'import serial; \
        print("serial.__version__ = {}".format(serial.__version__))'
    

    这只是导入 serial 模块并打印其 serial.__version__ 属性。 截至 2022 年 10 月,我的输出是:serial.__version__ = 3.5

    如果您的 pyserial 版本是 3.0 或更高版本,请在下面的代码中使用 property in_waiting。如果您的 pyserial 版本是 < 3.0,请在下面的代码中使用 function inWaiting()。在此处查看官方 pyserial 文档:https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting

非阻塞、单线程串行读取示例

import serial
import time # Optional (required if using time.sleep() below)

ser = serial.Serial(port='COM4', baudrate=9600)

while (True):
    # Check if incoming bytes are waiting to be read from the serial input 
    # buffer.
    # NB: for PySerial v3.0 or later, use property `in_waiting` instead of
    # function `inWaiting()` below!
    if (ser.inWaiting() > 0):
        # read the bytes and convert from binary array to ASCII
        data_str = ser.read(ser.inWaiting()).decode('ascii') 
        # print the incoming string without putting a new-line
        # ('\n') automatically after every print()
        print(data_str, end='') 

    # Put the rest of your code you want here
    
    # Optional, but recommended: sleep 10 ms (0.01 sec) once per loop to let 
    # other threads on your PC run during this time. 
    time.sleep(0.01) 

这样你只有在有东西的时候才能阅读和打印。你说,“理想情况下,我应该只有在可用时才能读取串行数据。”这正是上面的代码所做的。如果没有可读取的内容,它会跳到 while 循环中的其余代码。完全无阻塞。

(此答案最初在此处发布和调试:Python 3 non-blocking read with pySerial (Cannot get pySerial's "in_waiting" property to work))

pySerial 文档:http://pyserial.readthedocs.io/en/latest/pyserial_api.html

更新:

多线程注意事项:

尽管读取串行数据,如上所示,不需要需要使用多个线程,但以非阻塞方式读取键盘输入需要。因此,为了完成非阻塞键盘输入读取,我写了这个答案:How to read keyboard input?

引用资料:

  1. 官方pySerial serial.Serial() 类API - https://pyserial.readthedocs.io/en/latest/pyserial_api.html

关于python - PySerial 非阻塞读取循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17553543/

相关文章:

python - ndarray 到 Structured_array 和 float 到 int

python-3.x - 实时打印在 Python 中使用子进程启动的 bash 命令的结果

python - Python 3.x 中的字典采样

c - 如何终止非阻塞套接字连接尝试?

python - celery worker 与经纪人断开连接

python - "Too early"在 Keras 中提前停止

python - Tensorflow:InvalidArgumentError:预期的图像(JPEG,PNG或GIF),文件为空

c - 在套接字上使用 O_NONBLOCK 后,有没有办法避免 HUP?

scope - 是否可以将Verilog变量的局部作用域设置为always block ?

python - Django SQLite 在测试时试图覆盖数据库