53

Python 2.x has chr(), which converts a number in the range 0-255 to a byte string with one character with that numeric value, and unichr(), which converts a number in the range 0-0x10FFFF to a Unicode string with one character with that Unicode codepoint. Python 3.x replaces unichr() with chr(), in keeping with its "Unicode strings are default" policy, but I can't find anything that does exactly what the old chr() did. The 2to3 utility (from 2.6) leaves chr calls alone, which is not right in general :(

(This is for parsing and serializing a file format which is explicitly defined in terms of 8-bit bytes.)

zwol
  • 135,547
  • 38
  • 252
  • 361

6 Answers6

56

Try the following:

b = bytes([x])

For example:

>>> bytes([255])
b'\xff'
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
24

Consider using bytearray((255,)) which works the same in Python2 and Python3. In both Python generations the resulting bytearray-object can be converted to a bytes(obj) which is an alias for a str() in Python2 and real bytes() in Python3.

# Python2
>>> x = bytearray((32,33))
>>> x
bytearray(b' !')
>>> bytes(x)
' !'

# Python3
>>> x = bytearray((32,33))
>>> x
bytearray(b' !')
>>> bytes(x)
b' !'
Guido U. Draheim
  • 3,038
  • 1
  • 20
  • 19
9

Yet another alternative (Python 3.5+):

>>> b'%c' % 65
b'A'
Ecir Hana
  • 10,864
  • 13
  • 67
  • 117
  • Annoying that `b'{:c}'.format(65)` doesn't work as well, but thanks, this could be quite handy for the thing I originally wanted this for (and never got around to finishing). – zwol Oct 01 '18 at 17:07
8

In case you want to write Python 2/3 compatible code, use six.int2byte

youfu
  • 1,547
  • 3
  • 15
  • 21
  • I don't see why that would be better than Guido's answer, particularly if I have no other need for `six`. – zwol May 31 '16 at 18:21
  • @zwol: For Python 3.2+, `int2byte = operator.methodcaller("to_bytes", 1, "big")`. According to the comment, this is about 2x faster than `bytes((...))`. Anyway, `int2byte(x)` looks better than `bytes(bytearray((x,)))` for me. – youfu May 31 '16 at 18:29
  • Speed is good, but in the thing that provoked the original question, *no dependencies outside the standard library* was an overriding concern. – zwol May 31 '16 at 18:33
  • `bytes` takes a `tuple` for a constructor directly, so you can just use `bytes((x,))`. Only need to use `bytearray` if you want it to be mutable. – Perkins Sep 13 '16 at 08:11
7
>>> import struct
>>> struct.pack('B', 10)
b'\n'
>>> import functools
>>> bchr = functools.partial(struct.pack, 'B')
>>> bchr(10)
b'\n'
SangYoung Lee
  • 146
  • 1
  • 2
0

simple replacement based on small range memoization (should work on 2 and 3), good performance on CPython and pypy

binchr = tuple([bytes(bytearray((b,))) for b in range(256)]).__getitem__

binchr(1) -> b'\x01'
Glushiator
  • 630
  • 8
  • 8