No, this isn't a bug. This is normal behaviour. See this answer: the bytes type in python 2.7 and PEP-358

It basically comes down that the 2.7 bytes is just an alias for str to smoothen the transition to 3.x.

Answer from orlp on Stack Overflow
Discussions

How the write(), read() and getvalue() methods of Python io.BytesIO work? - Stack Overflow
I'm trying to understand the write() and read() methods of io.BytesIO. More on stackoverflow.com
🌐 stackoverflow.com
How to clear an io.BytesIO buffer.
That is the only way I found so ... pld.getvalue() becomes b''. I wonder if it is possible to clear buffer pld without recreating it, as object creation (and thus deletion and thus garbage collection) can be relatively costly on such a small processor. Beta Was this translation helpful? Give feedback. ... As a static pre-allocated bytearray seems to be the way to go, I'll try to use class StaticBuffer, shown below, as a replacement of class io.BytesIO... More on github.com
🌐 github.com
1
1
February 23, 2024
UnicodeDecodeError raised while trying to read io.BytesIO content
content=open(f.read(), 'rb') That's not how you use BytesIO. f is already a file-like object. Calling read() on it returns the contents of the file, and calling open on that treats the contents of the file as a file path to open. What you want to do is content=f. More on reddit.com
🌐 r/learnpython
3
1
September 25, 2020
python - When should one use BytesIO .getvalue() instead of .getbuffer()? - Stack Overflow
From the cpython code github.com/python/cpython/blob/master/Modules/_io/bytesio.c here, it seems when you call getvalue will resize the content buffer to strip off extra buffer space if allocated and getbuffer will return the buffer as it is ready to be modified if needed. More on stackoverflow.com
🌐 stackoverflow.com
🌐
DigitalOcean
digitalocean.com › community › tutorials › python-io-bytesio-stringio
Python io.BytesIO and io.StringIO: Memory File Guide | DigitalOcean
August 3, 2022 - import io stream_str = io.BytesIO(b"JournalDev Python: \x00\x01") print(stream_str.getvalue())
🌐
Python
docs.python.org › 3 › library › io.html
io — Core tools for working with streams
BufferedIOBase provides or overrides these data attributes and methods in addition to those from IOBase: ... The underlying raw stream (a RawIOBase instance) that BufferedIOBase deals with. This is not part of the BufferedIOBase API and may not exist on some implementations. ... Separate the underlying raw stream from the buffer and return it. After the raw stream has been detached, the buffer is in an unusable state. Some buffers, like BytesIO, do not have the concept of a single raw stream to return from this method.
🌐
GeeksforGeeks
geeksforgeeks.org › python › convert-from-_io-bytesio-to-a-bytes-like-object-in-python
Convert from '_Io.Bytesio' to a Bytes-Like Object in Python - GeeksforGeeks
July 23, 2025 - To convert from _io.BytesIO to a bytes-like object using the getvalue() method, we can directly obtain the byte data stored in the BytesIO buffer.
🌐
Python⇒Speed
pythonspeed.com › articles › bytesio-reduce-memory-usage
The surprising way to save memory with BytesIO
February 27, 2025 - Another options is BytesIO.getvalue(), which returns the contents of the BytesIO as a bytes object.
🌐
GeeksforGeeks
geeksforgeeks.org › python › stringio-and-bytesio-for-managing-data-as-file-object
Stringio And Bytesio For Managing Data As File Object - GeeksforGeeks
July 24, 2025 - In this example, a new BytesIO object named binary_buffer is created to emulate an in-memory file for binary data. The hexadecimal representation of the string "Hello" is written to the buffer using write. The content of the buffer is then retrieved as bytes with getvalue() and printed as the result. ... from io import BytesIO # Create a new BytesIO object binary_buffer = BytesIO() # Hexadecimal representation of "Hello" binary_buffer.write(b'\x48\x65\x6C\x6C\x6F') # Get the contents of the buffer as bytes result_bytes = binary_buffer.getvalue() # Print the result print(result_bytes)
Find elsewhere
🌐
HotExamples
python.hotexamples.com › examples › io › BytesIO › getvalue › python-bytesio-getvalue-method-examples.html
Python BytesIO.getvalue Examples, io.BytesIO.getvalue Python Examples - HotExamples
def writeOut( outputKey, image, metadata, heartbeat, outputToAccumulo, outputToLocalDirectory, outputDirectoryName, outputToStdOut ): if outputToAccumulo: heartbeat.write("%s write to Accumulo with key %s\n" % (time.strftime("%H:%M:%S"), outputKey)) buff = BytesIO() image.save(buff, "PNG", options="optimize") try: AccumuloInterface.write(outputKey, json.dumps(metadata), buff.getvalue()) except jpype.JavaException as exception: raise RuntimeError(exception.stacktrace()) if outputToLocalDirectory: heartbeat.write( "%s write to local filesystem with path %s/%s.png\n" % (time.strftime("%H:%M:%S"),
🌐
GitHub
github.com › python › cpython › blob › main › Modules › _io › bytesio.c
cpython/Modules/_io/bytesio.c at main · python/cpython
_io.BytesIO.getvalue · · Retrieve the entire contents of the BytesIO object. [clinic start generated code]*/ ·
Author   python
🌐
ProgramCreek
programcreek.com › python › example › 1734 › io.BytesIO
Python Examples of io.BytesIO
def _serialize_data(self, data): # Default to raw bytes type_ = _BYTES if isinstance(data, np.ndarray): # When the data is a numpy array, use the more compact native # numpy format. buf = io.BytesIO() np.save(buf, data) data = buf.getvalue() type_ = _NUMPY elif not isinstance(data, (bytearray, bytes)): # Everything else except byte data is serialized in pickle format.
🌐
Runebook.dev
runebook.dev › en › docs › python › library › io › io.BytesIO.getvalue
Beyond getvalue(): Efficiently Handling Binary Data with Python Streams
The io.BytesIO object is a stream that works with bytes in memory, much like a file but without actually touching the disk. The getvalue() method is used to retrieve the entire contents of the in-memory buffer as a bytes object.
🌐
Medium
medium.com › @sarthakshah1920 › harnessing-the-power-of-in-memory-buffers-with-bytesio-0ac6d5493178
Harnessing the Power of In-Memory Buffers with BytesIO | by Sarthak Shah | Medium
December 24, 2023 - ... Finally, we create an HTTP ... is set to the value obtained from file_buffer.getvalue(), which retrieves the entire content of the in-memory buffer....
🌐
Jamie Phillips
phillipsj.net › posts › odd-issue-using-bytesio-with-boto3
Odd Issue Using BytesIO With Boto3 • Jamie Phillips
September 28, 2023 - Then I realized that I probably shouldn’t be using read at all, I can just call getvalue and it will get all the contents of the stream. Here is the final example that is a little cleaner. stream = StringIO() writer = csv.writer(stream) writer.writerow(['Test1', 'Test2']) writer.writerow(['TestA', 'TestB']) client = boto3.client('s3') client.upload_fileobj(BytesIO(stream.getvalue().encode()), 'upload_bucket', 'csv_key'))
🌐
GitHub
github.com › orgs › micropython › discussions › 13708
How to clear an io.BytesIO buffer. · micropython · Discussion #13708
February 23, 2024 - Class StaticBuffer is (for now) modeled after class io.BytesIO. class StaticBufferException( Exception ): pass # 0 <= next <= lngt <= size class StaticBuffer(): def __init__( self, size ): self._bfr= bytearray( size ) self.size= size # Allocated size self.lngt= 0 # Current length self.next= 0 # Ordinal to start next write def clear( self ): self.lngt= 0 self.next= 0 def flush( self ): pass def getvalue( self ): return bytes(self._bfr[:self.lngt]) def seek( self, ordinal ): if ordina…
🌐
pythontutorials
pythontutorials.net › blog › how-the-write-read-and-getvalue-methods-of-python-io-bytesio-work
Python io.BytesIO Methods Explained: How write(), read(), and getvalue() Work – Key Differences & Usage Guide
Critical Takeaway: Use write() to add data, read() to fetch data from a specific position, and getvalue() to retrieve all data (ignoring the pointer). BytesIO shines when processing binary data (e.g., images) without saving to disk.
🌐
Reddit
reddit.com › r/learnpython › unicodedecodeerror raised while trying to read io.bytesio content
r/learnpython on Reddit: UnicodeDecodeError raised while trying to read io.BytesIO content
September 25, 2020 -

I'm trying to create a mock image for testing purposes; the scenario where a user uploads a photo on a website. Going through the linked S.O. topics has gotten me closer to that point by using io.BytesIO and the Pillow library.

  • Unit Testing a Django Form with a FileField

  • Django testing model with ImageField.

However, when I execute the test the following error is raised:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte. The interpreter is pointing at this:

content=open(f.read(), 'rb')

This topic is covered in S.O. as well, but with the most liked answer I can't seem to get it to work.

  • UnicodeDecodeError: 'utf-8' codec can't decode byte

I'm not sure how to go about addressing the error at this point.

**tests**

class RedundantImageUpload(TestCase):

    @classmethod
    def setUpTestData(cls):
        f = BytesIO()
        image = Image.new("RGB", (100, 100))
        image.save(f, 'png')
        f.seek(0)
        test_image = SimpleUploadedFile(
            "test_image.png",
            content=open(f.read(), 'rb'),
            content_type="image/png"
        )
        user = User.objects.create_user("User")
        import pdb; pdb.set_trace()
        form = PhotoForm({'title': "Image Title"}, {'source': test_image})
        instance = form.save(commit=False)
        instance.photographer = user
        instance.save()

        cls.submitted_form = PhotoForm(
            {'title': "Image Title"}, {'source': test_image}
        )


    def test_image_upload_path_exists(self):
        print("Here")
        print(self.submitted_form.errors)
Top answer
1 of 1
8

This question is old, but it looks like nobody has answered this sufficiently.

Simply:

  • obj.getbuffer() creates a memoryview object.
  • Every time you write, or if there is a memoryview of obj present, obj.getvalue() will need to create a new, complete value.
  • If you have not written (since creation or since the last obj.getvalue() call) and there is no memoryview present, obj.getvalue() is the fastest method of access, and requires no copies.

That being the case:

  • When creating another io.BytesIO, use obj.getvalue()
  • For random-access reading and writing, DEFINITELY use obj.getbuffer()
  • Avoid interpolating reading and writing frequently. If you must, then DEFINITELY use obj.getbuffer(), unless your file is tiny.
  • Avoid using obj.getvalue() while a buffer is laying around.

Here, we see that it's all fast, and all well and good if no buffer is laying around:


# time getvalue()
>>> i = io.BytesIO(b'f' * 1_000_000)
>>> %timeit i.getvalue()
34.6 ns ± 0.178 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

# time getbuffer()
>>> %timeit i.getbuffer()
118 ns ± 0.495 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

# time getbuffer() and getvalue() together
>>> %timeit i.getbuffer(); i.getvalue()
173 ns ± 0.829 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Everything is fine, and working about like you'd expect. But let's see what happens when there's a buffer just laying around:

>>> x = i.getbuffer()
>>> %timeit i.getvalue()
33 µs ± 675 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Notice that we're no longer measuring in nanoseconds, we're measuring in microseconds. That's multiple orders of magnitude slower. If you del x, we're back to being fast. This is all because while a memoryview exists, Python has to account for the possibility that the BytesIO may have been written to. So, to give a definite state to the user, it copies the buffer.

🌐
Jython
bugs.jython.org › issue1959
Issue 1959: io.BytesIO read method returns string "bytearray(b'...')" - Jython tracker
Created on 2012-08-15.11:25:33 by pjac, last changed 2012-08-18.06:20:44 by jeff.allen · Supported by Python Software Foundation, Powered by Roundup