1

I want to use NumPy arrays to efficiently operate on large byte arrays. Unfortunately, assigning a bytes object to a slice of the NumPy array does not work as I would expect:

import struct
import numpy as np

array = np.zeros(10, dtype=np.uint8)

# Store 65535 into the first two bytes
array[0:2] = struct.pack('<H', 65535)            # does not work

print(array)

This leads to the following exception:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)

In this example, the bytes object results from a call to struct.pack. When wrapping the result into a bytearray, everything works as intended, but I think this will perform an unnecessary copy operation (which is not what I want):

array[0:2] = bytearray(struct.pack('<H', 65535)) # works

Why does a bytes object not work here? The fact that bytearray is mutable whereas bytes is not should not make a difference here.

I'm using NumPy version 1.16.4.

1 Answer 1

3

You can create a memoryview which references the underlying buffer. This should avoid creating a copy.

array[:2] = memoryview(struct.pack('<H', 65535))
array
# array([255, 255,   0,   0,   0,   0,   0,   0,   0,   0], dtype=uint8)

It seems you cannot assign a byte string directly as NumPy attempts to decode the bytes into characters according to an encoding scheme (which would explain the UnicodeDecodeError) before assignment. With a bytearray or memoryview, it is implied that each byte is separate.

Sign up to request clarification or add additional context in comments.

2 Comments

According to the docs both bytes and bytearray do support the buffer protocol. So there must be some other difference, maybe it is the numpy implementation itself?
@ph4nt0m Only speculating here, I think the reason is that if you pass a byte string v/s a bytearray, numpy will try to decode the former according to a character encoding scheme. Whereas in a bytearray, the bytes are interpreted separately. Just my guess.

Your Answer

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.