40
votes

The shortest ways I have found are:

n = 5

# Python 2.
s = str(n)
i = int(s)

# Python 3.
s = bytes(str(n), "ascii")
i = int(s)

I am particularly concerned with two factors: readability and portability. The second method, for Python 3, is ugly. However, I think it may be backwards compatible.

Is there a shorter, cleaner way that I have missed? I currently make a lambda expression to fix it with a new function, but maybe that's unnecessary.

6
bytes(str(n),"ascii") is not backwards compatible, bytes() was introduced in python 3.x only. - Ashwini Chaudhary
I realize that you are trying to be broad to keep it from being to specific, but it's hard to tell why you're trying to do this or what exactly you're trying to achieve. - Tyler Crompton
@AshwiniChaudhary, I tried it at trypython.org/#, because my current Python is 3.3, but I acknowledge that that's hardly conclusive. - imallett
When bytes exists in 2, it's only an alias for str. bytearray exists, though, and has a bytearray(string, encoding[, errors]) -> bytearray call signature. - DSM
I think what @IgnacioVazquez-Abrams meant was that a network protocol would be more likely to want binary 0x05 rather than ASCII '5', but I know there are plenty of protocols that are text based. As for the double conversion to Unicode then raw bytes, it's eminently sensible when you've experienced the alternative. In Python 2 it's far too easy to get confused about whether you have a string of characters or a string of bytes and it leads to no end of bugs. - Mark Ransom

6 Answers

40
votes

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()

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'
39
votes

You can use the struct's pack:

In [11]: struct.pack(">I", 1)
Out[11]: '\x00\x00\x00\x01'

The ">" is the byte-order (big-endian) and the "I" is the format character. So you can be specific if you want to do something else:

In [12]: struct.pack("<H", 1)
Out[12]: '\x01\x00'

In [13]: struct.pack("B", 1)
Out[13]: '\x01'

This works the same on both python 2 and python 3.

Note: the inverse operation (bytes to int) can be done with unpack.

15
votes

I have found the only reliable, portable method to be

bytes(bytearray([n]))

Just bytes([n]) does not work in python 2. Taking the scenic route through bytearray seems like the only reasonable solution.

10
votes

Converting an int to a byte in Python 3:

    n = 5    
    bytes( [n] )

>>> b'\x05'

;) guess that'll be better than messing around with strings

source: http://docs.python.org/3/library/stdtypes.html#binaryseq

7
votes

from int to byte:

bytes_string = int_v.to_bytes( lenth, endian )

where the lenth is 1/2/3/4...., and endian could be 'big' or 'little'

form bytes to int:

data_list = list( bytes );
6
votes

In Python 3.x, you can convert an integer value (including large ones, which the other answers don't allow for) into a series of bytes like this:

import math

x = 0x1234
number_of_bytes = int(math.ceil(x.bit_length() / 8))

x_bytes = x.to_bytes(number_of_bytes, byteorder='big')

x_int = int.from_bytes(x_bytes, byteorder='big')
x == x_int