7

I would like to implement a class which inherits from RawIOBase. I'm struggling to implement the readinto method. Basically, I don't know how to alter the content of the bytearray object passed as a parameter.

I've tried following (naive) approach:

def readinto(self, b):
    data = self.read(len(b))
    b = data
    return len(data)

But this, as I suspect, will assign new bytearray object to local variable b and it does not change content of the original bytearray.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Luke
  • 71
  • 1
  • 2

1 Answers1

7

from the docs of RawIOBase.readinto:

Read bytes into a pre-allocated, writable bytes-like object b, and return the number of bytes read. If the object is in non-blocking mode and no bytes are available, None is returned.

its a bit confusing but you need to write into the bytes-like object b (not read)

Example Usage

import io

class MyIO(io.RawIOBase):
    def readinto(self, b):
        msg = b'hello'
        b[:len(msg)] = msg
        return len(msg)

i = MyIO()
buf = bytearray()
i.readinto(buf)
print(buf)

Take a look at CPython implementation of BytesIO.readinto. basically its does memcpy from the object's buffer to the function input buffer.

ShmulikA
  • 3,468
  • 3
  • 25
  • 40
  • 1
    also might work: https://docs.python.org/2/library/functions.html#bytearray instead of opening a fileobject. – jmunsch Aug 21 '17 at 20:55
  • Doesn't this incorrectly append the result to the end of the bytearray? It's clearly not empty, because he determines how much data to read based on the length of the incoming bytearray. – drglove Aug 21 '17 at 21:20
  • after looking at some implementations on the wild, I think you correct - updated the answer and comment – ShmulikA Aug 22 '17 at 05:22
  • 1
    I think this answer is still wrong (as of Python 3.8) `b[:len(msg)] = msg` is still expanding the length of the bytearray `b` if `len(msg) > len(b)` (this check is required to prevent that from happening; Without this, `read(x)` can return more than `x` bytes!) – pterodragon Aug 10 '20 at 06:59