How to transform integers into byte in the Python language?

Asked

Viewed 1,153 times

4

I’m using the pyserial module to send serial data, so I have a list of values like:

Valores = [10,20,30,40,50,60,70,80,90,100]

I need to transform the values of the list into bytes to send, because if I try to send it like this:

Serial.write(Valores)

Or so:

Serial.write(10)

I get that mistake:

File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 518, in write
    d = to_bytes(data)
  File "/usr/lib/python3/dist-packages/serial/serialutil.py", line 61, in to_bytes
    for item in seq:
TypeError: 'int' object is not iterable

But if send as the line below works!

Serial.write(b'10')

How can I make this conversion of values?

2 answers

6


In Python 3 the built-in "bytes" itself does this:

>>> bytes([40,10,20,30])
b'(\n\x14\x1e'

In Python 2, what today are "bytes" was the equivalent of strings. However in Python 3 they have separated: strings are text-containing objects, in which each element is a Unicode Codepoint - and it does not matter its numerical value, and the old "byte-string" became known as bytes, and works as in C: If by chance a value has an ASCII representation (numerical value from 32 to 128), it is printed, otherwise it is printed with hexadecimal two-digit encoding. Internally, it is only a numerical sequence of bytes, and is already the accepted type for all relevant functions dealing with the serial port.

In the case of your examples specifically, you can do:

serial.write(bytes((10,))

(the (10,) is a tuple of a single number - the final comma is not optional.

Or:

serial.write(b" x0a")

The prefix "b" for quotation marks indicates that it is a byte literal, not text - and you can place numbers directly in the hexadecimal notation within the quotation marks.

Since you are using serial communication, you may have to send data records with various fields of predetermined size. In this case, you can use the "struct" module that accompanies Python: it transforms a sequence of parameters according to a format string into a byte object, in the correct order - https://docs.python.org/3/library/struct.html

For example, if you have to send two 16-bit numbers without a signal, followed by a 32bit floating point number:

>>> struct.pack("<HHf", 40000, 50000, 3.28)
b'@\x9cP\xc3\x85\xebQ@'    

To extract the numbers of an object of type bytes, just use it as a normal sequence. In Python 3 an element of a byte sequence is an 8-bit signal-free number:

>>> a = b"minha_resposta:\xff"
>>> print(list(a))
[109, 105, 110, 104, 97, 95, 114, 101, 115, 112, 111, 115, 116, 97, 58, 255]

In Python 2 it is necessary to explicitly convert the byte element to integer - and the function can be used ord for that reason:

Python 2.7.14 (default, Jan 17 2018, 14:28:32) 
>>> a = b"minha_resposta:\xff"
>>> print(list(a))
['m', 'i', 'n', 'h', 'a', '_', 'r', 'e', 's', 'p', 'o', 's', 't', 'a', ':', '\xff']
>>> print(map(ord, a))
[109, 105, 110, 104, 97, 95, 114, 101, 115, 112, 111, 115, 116, 97, 58, 255]
  • Thank you so much for the excellent response! It worked!

  • Can you explain how to do the reverse path? Receive bytes and transform into integers.

6

  • only if you are coding numbers that use more than 1 byte . But in the case of communication with the serial, it will be better to use the struct Why is the chance that the numbers are filled fields inside several other.

  • @jsbueno yes, I was complementing with the two options

Browser other questions tagged

You are not signed in. Login or sign up in order to post.