randomAsker randomAsker - 1 year ago 67
Python Question

How to extract and change a sequence of bytes from a serial packet to the correct integer representation in python?


This is the serial packet I am processing using pyserial. The two bytes in bold actually correspond to a real world measurement which corresponds to
(decimal) or
(hex). How do I extract those bytes in python and get the correct int value which is 721?

Answer Source

Processing to and from such byte strings is quickly and easily done with the struct library functions pack/pack_to and unpack/unpack_from:

While it is normally best practice to unpack/unpack the entire packet you can use the _from & _to versions to selectively manipulate packets.

In your case:

>>> import struct
>>> val # Generated using  binascii.unhexlify
>>> struct.unpack_from('<H', val, 10)
(721,) # Note the return is a tupple so you need the 0th element
>>> struct.unpack_from('<H', val, 10)[0]

More info

>>> import struct
>>> help (struct.unpack)
Help on built-in function unpack in module _struct:

    unpack(fmt, buffer) -> (v1, v2, ...)

    Return a tuple containing values unpacked according to the format string
    fmt.  Requires len(buffer) == calcsize(fmt). See help(struct) for more
    on format strings.
>>> help (struct.pack)
Help on built-in function pack in module _struct:

    pack(fmt, v1, v2, ...) -> bytes

    Return a bytes object containing the values v1, v2, ... packed according
    to the format string fmt.  See help(struct) for more on format strings.

>>> help(struct)
Help on module struct:


    Functions to convert between Python values and C structs.
    Python bytes objects are used to hold the data representing the C struct
    and also as format strings (explained below) to describe the layout of data
    in the C struct.

    The optional first format char indicates byte order, size and alignment:
      @: native order, size & alignment (default)
      =: native order, std. size & alignment
      <: little-endian, std. size & alignment
      >: big-endian, std. size & alignment
      !: same as >

    The remaining chars indicate types of args and must match exactly;
    these can be preceded by a decimal repeat count:
      x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;
      ?: _Bool (requires C99; if not available, char is used instead)
      h:short; H:unsigned short; i:int; I:unsigned int;
      l:long; L:unsigned long; f:float; d:double.
    Special cases (preceding decimal count indicates length):
      s:string (array of char); p: pascal string (with count byte).
    Special cases (only available in native format):
      n:ssize_t; N:size_t;
      P:an integer type that is wide enough to hold a pointer.
    Special case (not in native mode unless 'long long' in platform C):
      q:long long; Q:unsigned long long
    Whitespace between formats is ignored.

    The variable struct.error is an exception raised on errors.