4

As noted here receiving a message through a Micropython socket results in being left with a byte string to work with. My question is how to convert this byte string to another usable format?

I have tried the likes of:

data = s.recv(64)
new = hex(data)

which results in errors such as:

TypeError: can't convert bytes to int

And: data = s.recv(64).hex() Resulting in:

AttributeError: 'bytes' object has no attribute 'hex'

I am fairly new to Python and Micro-python in general. As far as I can tell this has not been answered directly for Micropython.

If this has been answered specifically for Python3 I think it worthwhile to re-iterate it for Micropython since implementation can be slightly different and to perhaps find an acceptable 'best practice'.

goldfishalpha
  • 447
  • 2
  • 4
  • 13

6 Answers6

4

It's not clear exactly what you're trying to do.

The way you convert bytes into a string is by calling the .decode method. This gives you bytes:

data = s.recv(64)

And this transforms that into a string:

data = data.decode('utf-8')

But you're trying to call hex(), which takes a single integer and returns the corresponding hexadecimal value. That doesn't make much sense in the context of your question.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • @ larsks Thank you, what I was trying to achieve was one or both of two things: 1. To make the data usable (if statements etc), 2.calling 'hex() was to 'cast' the incoming data in hex format so that it could be displayed as such when printed out. Clearly my knowledge pertaining to data types is lacking. – goldfishalpha Mar 07 '19 at 09:52
3

I needed to convert a byte MAC address to a string representing hex values. @birdistheword99 showed me the way...

a MAC address retrieved from the system looks like: b'\xacg\xb27-\xcc'. This is not very reader friendly. To make it into a string of hex digits...

import binascii

mac_bytes = b'\xacg\xb27-\xcc'
mac_str = binascii.hexlify(mac_bytes).decode()
print(mac_str)

Yields...

ac67b2372dcc
stanely
  • 342
  • 1
  • 8
2

Have you tried import struct?

new = struct.unpack('=i', data)
phil
  • 561
  • 3
  • 10
1

So what you have is a bytes object, and it sounds like what you want is a string containing the hexadecimal representation of those bytes.

The answers to this question describe how to do this in standard Python, but from a quick check with the online MicroPython console you can't just call .hex() on the bytes object itself, and we don't have the binascii or codecs modules, so none of those methods will work.

However it's not difficult to do what you want with plain Python:

>>> data = b'hello!'
>>> ''.join(['{:02x}'.format(b) for b in data])
'68656c6c6f'

Here we're using a list comprehension to get each byte b in turn from the bytes object data. We're then formatting that into a two-character string in hexadecimal format, with a leading zero if necessary, using '{:02x}'.format(b). The expression inside the square brackets gives us a list of those two-character strings, so finally we join them together separated by an empty string.

If you want a space between each two-digit group, for example, replace the '' with ' '.

I find this a useful starting point for string formatting methods in Python. MicroPython supports the %-operator and str.format methods, but not formatted string literals.

nekomatic
  • 5,988
  • 1
  • 20
  • 27
  • Actually there is a ubinascii module which contains the hexlify and unhexlify functions, and can be imported as 'ubinascii' or just 'binascii': [https://docs.micropython.org/en/latest/library/ubinascii.html](https://docs.micropython.org/en/latest/library/ubinascii.html) – birdistheword99 Jun 10 '20 at 14:52
1

While I think @larsks answer is the best (calling the '.deocde()'), you originally said that you wanted it in hex.

It's worth noting that the ubinascii module is available on most micropython ports and has a 'hexlify' function for converting to hex. It will still return a bytes string though, so you may still need to call .decode() depending on your intended purpose: https://docs.micropython.org/en/latest/library/ubinascii.html

You might also want to look at the builtin 'from_bytes' class method built into the 'int' type. You can use it with:

x = int.from_bytes(byte_string, byte_order)

https://docs.micropython.org/en/latest/library/builtins.html?highlight=to_bytes

birdistheword99
  • 179
  • 1
  • 15
0

Minimal example:

import network
import binascii 
print(binascii.hexlify(network.WLAN(network.STA_IF).config('mac')).decode())
Knemay
  • 350
  • 1
  • 6
  • 12