Я пишу приложение на Python 3, которое общается с устройством через последовательный порт, используя модуль pyserial.
При записи на устройство модуль pyserial ожидает, что данные будут представлены в виде последовательности байтов.
Это прекрасно работает, если я записываю данные сразу, но не работает, если я записываю данные побайтно с задержкой после каждого байта. Причина, по которой я хочу писать побайтно, заключается в том, что мне приходится иметь дело с устройствами, которые могут обрабатывать данные только с низкой скоростью.
Код, который я использую:
def write_timed(self, data):
"""Write data to serial port,
taking into account inter-character delay and line-delay
:param data (str): string to write; any escaped characters will be converted
e.g. \n will be output as a newline (not as characters '\' and 'n')
"""
# convert raw string to sequence of bytes
data = bytes(data.encode('latin-1').decode("unicode_escape"), "latin-1")
logging.info("TX:{}".format(repr(data)))
# only write to device if we have something to write
if data:
if data and self.char_delay_s == 0:
self.serial.write(data)
else:
for d in data:
self.serial.write(d)
time.sleep(self.char_delay_s)
time.sleep(self.line_delay_s)
# ensure all data has gone out
self.serial.flush()
Ошибка, которую я получаю:
File "C:\projects\maintenance\protocoltest\protocoltest\device\device.py", line 65, in write_timed
self.serial.write(d)
File "C:\projects\newplatform\venv3_pyside2\lib\site-packages\serial\serialwin32.py", line 301, in write
data = to_bytes(data)
File "C:\projects\newplatform\venv3_pyside2\lib\site-packages\serial\serialutil.py", line 61, in to_bytes
for item in seq:
TypeError: 'int' object is not iterable
Причина ошибки в том, что когда я запускаю for d in data:, переменная d становится int вместо последовательности байтов длиной 1.
Если я попытаюсь исправить это с помощью d = bytes(d), я получу строку нулей, длину значения d.
Как я могу записать отдельные байты в pyserial?
Если я установлю self.char_delay_s на ноль, все будет работать нормально, даже строки длиной 1. Если у меня есть ненулевое значение, я получу ошибку выше.





К сожалению, как вы обнаружили, когда вы индексируете объект bytes, вы получаете объект int. Проще всего просто преобразовать этот int обратно в bytes:
for d in data:
d = bytes([d])
# d is now a bytes object and can be used as such
В качестве альтернативы вы можете использовать срезы вместо индексации:
for i in range(len(data)):
d = data[i : i + 1]
# d is a bytes object because it's a slice of a bytes object