Converting int to bytes in Python 3
Python 3.5+ introduces %-interpolation (printf
-style formatting) for bytes:
>>> b'%d\r\n' % 3
b'3\r\n'
See PEP 0461 -- Adding % formatting to bytes and bytearray.
On earlier versions, you could use str
and .encode('ascii')
the result:
>>> s = '%d\r\n' % 3
>>> s.encode('ascii')
b'3\r\n'
Note: It is different from what int.to_bytes
produces:
>>> n = 3
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big') or b'\0'
b'\x03'
>>> b'3' == b'\x33' != b'\x03'
True
Convert int to byte in Python
Convert the int
to a str
then .encode
into bytes
:
>>> x = 123456
>>> bs = str(x).encode('ascii')
>>> bs
b'123456'
Convert n-byte int to bytes in python3
I'm guessing you need a 32-bit integer, and big-endian to boot:
>>> from ctypes import c_uint32
>>> l = c_uint32(0x12345678)
>>> bytes(l)
b'xV4\x12'
There is c_uint8, c_uint16 and c_uint64 as well. For longer ints you need to make it manually, using divmod(x, 256).
>>> def bytify(v):
... v, r = divmod(v, 256)
... yield r
... if v == 0:
... raise StopIteration
... for r in bytify(v):
... yield r
...
>>> [x for x in bytify(0x12345678)]
[120, 86, 52, 18]
>>> bytes(bytify(0x12345678))
b'xV4\x12
>>> bytes(bytify(0x123456789098765432101234567890987654321))
b'!Ce\x87\t\x89gE#\x01!Ce\x87\t\x89gE#\x01'
Python 3 Converting integers to bytes correctly:
Those two examples are not equivalent. str(n).encode()
takes whatever you give it, turns it into its string representation, and then encodes using a character codec like utf8. bytes([..])
will form a bytestring with the byte values of the array given. The representation \xFF
is in fact the hexadecimal representation of a single byte value.
>>> str(8).encode()
b'8'
>>> b'8' == b'\x38'
True
Python 2,3 Convert Integer to bytes Cleanly
Answer 1:
To convert a string to a sequence of bytes in either Python 2 or Python 3, you use the string's encode
method. If you don't supply an encoding parameter 'ascii'
is used, which will always be good enough for numeric digits.
s = str(n).encode()
- Python 2: http://ideone.com/Y05zVY
- Python 3: http://ideone.com/XqFyOj
In Python 2 str(n)
already produces bytes; the encode
will do a double conversion as this string is implicitly converted to Unicode and back again to bytes. It's unnecessary work, but it's harmless and is completely compatible with Python 3.
Answer 2:
Above is the answer to the question that was actually asked, which was to produce a string of ASCII bytes in human-readable form. But since people keep coming here trying to get the answer to a different question, I'll answer that question too. If you want to convert 10
to b'10'
use the answer above, but if you want to convert 10
to b'\x0a\x00\x00\x00'
then keep reading.
The struct
module was specifically provided for converting between various types and their binary representation as a sequence of bytes. The conversion from a type to bytes is done with struct.pack
. There's a format parameter fmt
that determines which conversion it should perform. For a 4-byte integer, that would be i
for signed numbers or I
for unsigned numbers. For more possibilities see the format character table, and see the byte order, size, and alignment table for options when the output is more than a single byte.
import struct
s = struct.pack('<i', 5) # b'\x05\x00\x00\x00'
Convert bytes to int?
Assuming you're on at least 3.2, there's a built in for this:
int.from_bytes
(bytes
,byteorder
, *,signed=False
)...
The argument
bytes
must either be a bytes-like object or an iterable
producing bytes.The
byteorder
argument determines the byte order used to represent the
integer. Ifbyteorder
is"big"
, the most significant byte is at the
beginning of the byte array. Ifbyteorder
is"little"
, the most
significant byte is at the end of the byte array. To request the
native byte order of the host system, usesys.byteorder
as the byte
order value.The
signed
argument indicates whether two’s complement is used to
represent the integer.
## Examples:
int.from_bytes(b'\x00\x01', "big") # 1
int.from_bytes(b'\x00\x01', "little") # 256
int.from_bytes(b'\x00\x10', byteorder='little') # 4096
int.from_bytes(b'\xfc\x00', byteorder='big', signed=True) #-1024
Python: convert from INT to BYTES issue
Python represents bytes
in such a way that if a value is printable ASCII, it will use that instead of an escape sequence. You can try it out:
>>> b'\x0a'
b'\n'
>>> b'\x32'
b'2'
And it checks out: \n
is Python's escape sequence for newline (ASCII character 10), and 2
is ASCII character 50.
Convert back from int to byte
You can accomplish this using the int
to_bytes
method. Here is an example:
value = int.from_bytes(bytevalues, byteorder='big')
new_bytevalues = value.to_bytes(length=len(bytevalues), byteorder='big')
print(new_bytevalues == bytevalues) # prints True
In to_bytes
, we have to define length to be at least the size of the original bytes
object. If it is not, it will cause an OverflowError
. It can be bigger than the length of the original bytes
object, and in that case it will just pad the result with zeros.
Python3 How to make a bytes object from a list of integers
Just call the bytes
constructor.
As the docs say:
… constructor arguments are interpreted as for
bytearray()
.
And if you follow that link:
If it is an iterable, it must be an iterable of integers in the range
0 <= x < 256
, which are used as the initial contents of the array.
So:
>>> list_of_values = [55, 33, 22]
>>> bytes_of_values = bytes(list_of_values)
>>> bytes_of_values
b'7!\x16'
>>> bytes_of_values == '\x37\x21\x16'
True
Of course the values aren't going to be \x55\x33\x22
, because \x
means hexadecimal, and the decimal values 55, 33, 22
are the hexadecimal values 37, 21, 16
. But if you had the hexadecimal values 55, 33, 22
, you'd get exactly the output you want:
>>> list_of_values = [0x55, 0x33, 0x22]
>>> bytes_of_values = bytes(list_of_values)
>>> bytes_of_values == b'\x55\x33\x22'
True
Converting integers to Bytes in python
It looks like you're working on building out a IPv4 packet header (you should've mentioned this in your question, assuming you know this to be the case).
Your logic currently takes the version
and appends it to your byte array as a whole byte (8 bits), but it should only occupy the first 4 bits (or 1 nibble).
You're likely expecting the first byte to be "E" because 0b0100_0101
(that is, 4 represented as 4 bits
followed by 5 represented as 4 bits
, as shown in the diagram below) is 69 in decimal, which is the ASCII character for "E". So, if you were to run strings
or hexdump
on a TCPv4 packet, you might see "E" as the first character. However, the first byte should actually be 0x45
, so you're confusing the representations of the initial byte.
Your code isn't quite right because it's treating the version
and hdrlen
as two separate bytes when they should be in the same byte as two separate nibbles.
So, you want something like:
first_byte = version << 4 | length
This should give you enough direction. Best of luck.
Related Topics
Python and Regular Expression with Unicode
Create a .CSV File with Values from a Python List
Positional Argument V.S. Keyword Argument
Merge Lists That Share Common Elements
How to Find Script's Directory
What Does Preceding a String Literal with "R" Mean
Appending Turns My List to Nonetype
What's the Difference Between Dist-Packages and Site-Packages
Weighted Random Selection with and Without Replacement
Python Ctypes - Loading Dll Throws Oserror: [Winerror 193] %1 Is Not a Valid Win32 Application
Convert String in Base64 to Image and Save on Filesystem
Convert Pandas.Series from Dtype Object to Float, and Errors to Nans
How to Find Length of Digits in an Integer
How to Include Third Party Python Libraries in Google App Engine