Search code examples
pythonpython-3.xstringlisthex

How to convert a lists of integers to a string of the individual bytes?


I'm trying to print a list of bytes to a file in hex (or decimal, doesn't really make a difference for the sake of the question I believe). I'm baffled by how hard this appears to be in Python?

Based on what I found here (and on other SO questions), I already managed to do this:

>>> b
[12345, 6789, 7643, 1, 2]
>>> ' '.join(format(v, '02x') for v in b)
'3039 1a85 1ddb 01 02'

Now... this is already a good start, but... for larger numbers the individual bytes are grouped and attached to each other. This should not happen. There should be a space between them, just like is the case with the two last numbers.

Of course, I could just do some string manipulation afterwards and insert some spaces, but... that sounds like a very hacky way, and I refuse to believe there isn't a cleaner way to do this.

So, what I want is this:

'30 39 1a 85 1d db 00 01 00 02'

How can I do this?


Solution

  • So, you want to create a hexdump-like output. Given your example inputs/outputs, it sounds like you want the big-endian, 16-bit length bytes from the integers in your list. The key is to use int.to_bytes. Here is a function that first creates a list of bytes from the integers, then iterates over the individual bytes, formatting them as requested:

    def hexdump(
        data: list[int], length=2, byteorder: str = "big", fmt: str = "02x", sep: str = " "
    ) -> str:
        bytes_data = (i.to_bytes(length=length, byteorder=byteorder) for i in data)
        return sep.join([f"{b:{fmt}}" for bs in bytes_data for b in bs])
    
    

    Here are some examples of it in use:

    In [2]: data = [12345, 6789, 7643, 1, 2]
    
    In [3]: hexdump(data)
    Out[3]: '30 39 1a 85 1d db 00 01 00 02'
    
    In [4]: hexdump(data, length=4, fmt='04x')
    Out[4]: '0000 0000 0030 0039 0000 0000 001a 0085 0000 0000 001d 00db 0000 0000 0000 0001 0000 0000 0000 0002'
    
    In [5]: hexdump(data, sep="|")
    Out[5]: '30|39|1a|85|1d|db|00|01|00|02'