Readlines () PySerial потребляет в 25 раз больше процессорного времени, чем read ()

Я читаю постоянный поток данных через последовательный порт, используя pyserial:

import serial
s = serial.Serial('/dev/ttyACM0', 9600)

Если я использую метод .read, например, этот

while True:
    print(s.read(1000))

Потребляет примерно 1-2% ЦП.

Но если я начну собирать их списком, что удобнее, вот так

while True:
    print(s.readlines(1000))

Загрузка процессора внезапно возрастает до 50%, что кажется немного неразумным, только разница вывода разделяется на новые строки.

Я что-то делаю не так, есть ли способ заставить метод readlines () более экономно использовать процессор?

Спасибо

# python-3.x pyserial
Источник
  • 0
    Странный. Я знаю, что .readlines округляется, чтобы закончить текущую строку, на которой он находится, но, конечно, это не должно вызывать такой большой разницы. Вызывает ли использование s.readline() такую же проблему?
  • 0
    У меня нет объяснений. Чтения должны блокироваться, если timeout=0 не равен 0. pyserial есть .readuntil() , тоже проблемы? Ссылка: pyserial.readthedocs.io/en/latest/…
  • 0
    @RolvApneseth Да, readline () действует так же, как readlines () в этом случае.
  • 0
    @VPfB Да, read_until () тоже ест 50%, ожидая новой строки
  • 0
    @Kasami Я кратко проверил источник. read_until вызывает read(1) . Странно, что read(1000) в порядке, а read(1) - нет. Возможно, вам стоит сообщить о проблеме автору.
Codelisting
за 4 против
Лучший ответ

Я предполагаю, чтоreadlines а такжеreadline деловито опрашивать последовательную строку на предмет новых символов, чтобы выполнить ваш запрос на получение полной строки (или строк), тогда как.read будет читать и возвращаться только тогда, когда действительно есть новые данные. Вероятно, вам придется самостоятельно реализовать буферизацию и разбиение на строки (код не тестировался, так как у меня сейчас нет ничего на последовательной линии :-)):

import serial


def read_lines(s, sep=b"\n"):
    buffer = b""
    while True:
        buffer += s.read(1000)
        while sep in buffer:
            line, _, buffer = buffer.partition(sep)
            yield line


s = serial.Serial("/dev/ttyACM0", 9600)

for line in read_lines(s):
    print(line)
  • 0
    Спасибо! Это решение с буферизацией работает и занимает 2-2,5% ЦП, чего я и ожидал. Очень удивительно, что это не часть pyserial!
Codelisting
Популярные категории
На заметку программисту