PySerial非阻塞读取循环

Dom*_*icM 28 python nonblocking pyserial python-3.x

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

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()
Run Code Online (Sandbox Code Playgroud)

问题是它阻止了其他任何事情的执行,包括瓶子py web框架.添加sleep()无济于事.

在ser.readline()中更改"while True""to":"不打印"test",这很奇怪,因为它在Python 2.7中有效.任何想法可能出错?

理想情况下,只有在可用时才能读取串行数据.数据每1,000毫秒发送一次.

Fre*_*ård 40

把它放在一个单独的线程中,例如:

import threading
import serial

connected = False
port = 'COM4'
baud = 9600

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

def handle_data(data):
    print(data)

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

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

thread = threading.Thread(target=read_from_port, args=(serial_port,))
thread.start()
Run Code Online (Sandbox Code Playgroud)

http://docs.python.org/3/library/threading


Gab*_*les 40

使用单独的线程是完全没必要的.只需为你的无限循环执行此操作(在Python 3.2.3中测试):

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

while (True):
    # NB: for PySerial v3.0 or later, use property `in_waiting` instead of function `inWaiting()` below!
    if (ser.inWaiting()>0): #if incoming bytes are waiting to be read from the serial input buffer
        data_str = ser.read(ser.inWaiting()).decode('ascii') #read the bytes and convert from binary array to ASCII
        print(data_str, end='') #print the incoming string without putting a new-line ('\n') automatically after every print()
    #Put the rest of your code you want here
    time.sleep(0.01) # Optional: sleep 10 ms (0.01 sec) once per loop to let other threads on your PC run during this time. 
Run Code Online (Sandbox Code Playgroud)

这样,只有在有东西的情况下才能阅读和打印.你说,"理想情况下,只有当串行数据可用时才能读取它." 这正是上面的代码所做的.如果没有任何内容可供阅读,它会跳转到while循环中的其余代码.完全没有阻塞.

(这个答案最初发布和调试在这里:Python 3无阻塞读取pySerial(无法使pySerial的"in_waiting"属性工作))

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

更新:

关于多线程的注意事项:

即使读串行数据,如上所示,它要求使用多个线程,读取键盘输入在非阻塞方式确实.因此,为了完成非阻塞键盘输入读取,我写了这样的答案:如何读取键盘输入?.

  • 而不是while(True)我建议使用while(ser.isOpen()) (3认同)
  • 如果您没有阻塞,我建议在 if..inWaiting 块中使用 else 子句,并使用 time.sleep(0.01) 来避免“挂钩”计算机的 CPU,如果您想同时运行其他任何东西. (2认同)