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
🌐
Python
docs.python.org › 3 › library › io.html
io — Core tools for working with streams
The BufferedIOBase ABC extends IOBase. It deals with buffering on a raw binary stream (RawIOBase). Its subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer raw binary streams that are writable, readable, and both readable and writable, respectively. BufferedRandom provides a buffered interface to seekable streams. Another BufferedIOBase subclass, BytesIO, is a stream of in-memory bytes.
🌐
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.
🌐
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⇒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.
🌐
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"),
🌐
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
🌐
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.
🌐
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....
🌐
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.
🌐
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…
🌐
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'))
🌐
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.

🌐
AskPython
askpython.com › home › python io module: the complete practical reference
Python IO Module: The Complete Practical Reference - AskPython
February 16, 2023 - Here, getvalue() takes the value of the byte string from the handle. Since the byte string \x0A is the ASCII representation of the newline (‘\n’), we get the following output: ... Now, it is always a good practice to close our buffer handle ...