Непрерывный цикл считывания 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()

Проблема заключается в том, что она предотвращает выполнение каких-либо других функций, включая флеш-флеш-память. Добавление sleep() не поможет.

Изменение "while True" "до", в то время как ser.readline(): "не печатает" тест ", что странно, поскольку он работал в Python 2.7. Любые идеи, что может быть неправильным?

В идеале я должен иметь возможность читать последовательные данные только тогда, когда они доступны. Данные отправляются каждые 1000 мс.

Ответы

Ответ 1

Поместите это в отдельную ветку, например:

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()

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

Ответ 2

Использование отдельного потока совершенно не нужно. Просто сделайте это для своего бесконечного цикла while (протестировано в 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. 

Таким образом, вы только читаете и печатаете, если что-то есть. Вы сказали: "В идеале я должен иметь возможность читать последовательные данные только тогда, когда они доступны". Это именно то, что делает код выше. Если ничего не доступно для чтения, он пропускает остальную часть вашего кода в цикле while. Полностью неблокируемый.

(Этот ответ первоначально был опубликован и отлажен здесь: неблокирующее чтение Python 3 с помощью pySerial (не удается заставить работать свойство inSwaiting) pySerial))

Документация pySerial: http://pyserial.readthedocs.io/en/latest/pyserial_api.html

ОБНОВИТЬ:

Примечание по многопоточности:

Хотя чтение последовательных данных, как показано выше, не требует использования нескольких потоков, чтение неблокируемого ввода с клавиатуры делает это. Поэтому, чтобы выполнить неблокирующее чтение с клавиатуры, я написал такой ответ: Как читать ввод с клавиатуры? ,

Ответ 3

Используйте управляемое таймером событие для тестирования и чтения последовательного порта. Непроверенный пример:

import threading
class serialreading():
    def __init__(self):
        self.active = True
        self.test() 
    def test(self):
        n_in =comport.in_waiting()
        if n_in> 0:
            self.data = self.data + comport.read(size=n_in)
    if len(self.data) > 0: 
        print(self.data)
        self.data=""
    if self.active:
        threading.Timer(1, test).start()  # start new timer of 1 second
    def stop(self):
        self.active = False

Ответ 4

Я бы предостерег от использования блокировки ввода-вывода в потоке. Помните, что в Python есть GIL, и одновременно может выполняться только один поток. Теперь обратите внимание, что модуль pyserial является оболочкой для реализации ОС доступа к последовательному порту. Это означает, что он вызывает код, внешний по отношению к Python. Если этот код блокируется, то интерпретатор также блокируется, и в программе Python ничего не будет выполняться, даже основной поток.

Это может даже произойти при использовании неблокирующего ввода-вывода или опроса на основе тайм-аута, если базовый драйвер устройства не реализует тайм-аут хорошо.

Более надежный подход заключается в использовании многопроцессорного модуля с очередью. Запустите последовательный код чтения в отдельном процессе. Это позволит убедиться, что основной и другие потоки не блокируются, и программа может выйти чистым способом.