7

I want to convert an 32-byte (although I might need other lengths) integer to a bytes object in python. Is there a clean and simple way to do this?

asked Jan 18, 2011 at 21:15
3
  • What format has your integer currently? Commented Jan 18, 2011 at 21:18
  • 5
    32-byte integer? That's a lot of nu... bytes. What exactly are you trying to achieve, and what did you already try? Commented Jan 18, 2011 at 21:18
  • I have sha hashes in 0x... form, python is perfectly happy converting them to integers, but how do I get from there to bytes? Commented Jan 18, 2011 at 21:37

4 Answers 4

9

to_bytes (length, byteorder[, signed]) is all you need starting from 3.2. In this case, someidentifier.to_bytes(4,'big') should give you the bytes string you need.

answered Mar 20, 2012 at 3:20
Sign up to request clarification or add additional context in comments.

4 Comments

>>> hash.to_bytes(32) ... Traceback (most recent call last): ... File "<pyshell#28>", line 1, in <module> ... hash.to_bytes(32) ... AttributeError: 'builtin_function_or_method' object has no ... attribute 'to_bytes'
Next time I'll use a different identifier; 'hash' was meant to be the actual variable name or literal, not the builtin. I forgot there was such a builtin, my bad. byteorder is also required now.
The length argument to to_bytes is in bytes, not bits, so it should be 4 instead of 32.
It's a pity you have to specify length--it should provide a means to automatically make the minimum required length to represent the integer.
3

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'
answered Jan 18, 2011 at 21:50

5 Comments

There is no need to use ctypes: bytes can be initialised with an array of ints in the range (0, 256).
Dear @Lennart, you started your answer with importing ctypes. You went on to show ctypes of various sizes. Then you provided a solution that doesn't use them (which I personally think should have been the first solution) - without saying so explicitly. I just thought it was important to explicitly mention the fact, that's all. You have the right to disagree, and you don't have to rephrase your answer if you don't see it fit, but there's no need to throw accusations. I said what I said because I think some people may get the wrong impressions that ctypes are needed and be discouraged by that.
The ctypes answer is faster, I still think it's the best answer at that time (although of course now you can switch to 3.2 and use to_bytes())
Thanks for the bytify generator. It is useful if you do not know the size of the number. But just for the record: You are encoding the numbers using little-endian byte order, not big-endian.
Ah, right, big-endian means the little number comes at the end. I always get that confused. Easy to fix with a reverse() of course.
3

You can use bytes("iterable") directly. Where every value in iterable will be specific byte in bytes(). Example for little endian encoding:

>>> var=0x12345678
>>> var_tuple=((var)&0xff, (var>>8)&0xff, (var>>16)&0xff, (var>>24)&0xff)
>>> bytes(var_tuple)
b'xV4\x12'
Be Brave Be Like Ukraine
7,8153 gold badges48 silver badges69 bronze badges
answered Nov 14, 2012 at 14:31

Comments

1

Suppose you have

var = 'і' # var is ukrainian і

We want to get binary from it. Flow is this. value/which is string => bytes => int => binary

binary_var = '{:b}'.format(int.from_bytes(var.encode('utf-8'), byteorder='big'))

Now binary_var is '1101000110010110'. It type is string.

Now go back, you want get unicode value from binary:

int_var = int(binary_var, 2) # here we get int value, int_var = 53654

Now we need convert integer to bytes. Ukrainian 'і' is not gonna fit into 1 byte but in 2. We convert to actual bytes bytes_var = b'\xd1\x96'

bytes_var = int_var.to_bytes(2, byteorder='big') 

Finally we decode our bytes.

ukr_i = bytes_var.decode('utf-8') # urk_i = 'і'
answered Dec 25, 2017 at 11:18

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.