Table of Contents

What Will You Learn
You’ll learn how to create, convert, and modify binary objects, work with encodings, and handle binary files in practical applications like networking and image processing.


Working with binary data is an integral part of programming, especially in tasks related to file processing, network protocols, images, byte streams, and low-level interaction with external devices. In these cases, data is represented not as text but in binary (byte) format.

The programming language provides built-in data types for handling binary information: bytes, bytearray, and memoryview. These types allow you to work with bytes directly, safely, and efficiently. They are used when reading and writing binary files (.jpg, .exe, .pdf), in encryption, network programming, and memory optimization.

For beginners, it's important to understand that binary types are not an alternative to strings, but a completely different category intended for specific, yet critically important tasks.

What are binary data types in Python?

Binary data types are types designed to store and process sequences of bytes. Each byte represents an integer from 0 to 255. These types are not intended for direct text manipulation but are actively used in file handling, network streams, buffers, and data transmission between programs and devices.

There are three main binary types:

Data Type Mutability Description Used For
bytes ❌ No Immutable sequence of bytes File I/O, serialization, networking
bytearray ✅ Yes Mutable array of bytes Buffers, dynamic binary modification
memoryview ✅ Yes View object over another byte object without copying Memory optimization, data slicing

Each type has its own behavior, characteristics, and use cases. For example, bytes is used when loading an image from a file, bytearray—when incrementally forming a binary packet, and memoryview—for manipulation without extra memory overhead.

What is Bytes?

bytes is an immutable sequence of bytes, where each byte is an integer from 0 to 255. It is a fundamental type for representing raw binary data, which behaves like a string but stores byte values instead of characters.


    data = b"Hello"
    print(data)        # b'Hello'
    print(data[0])     # 72 (ASCII code of 'H')
  

A key feature is immutability. Once created, a bytes object cannot be changed: you cannot add, remove, or replace a byte. This makes it safe for transmission and use in functions where accidental changes must be avoided.

How to Create Bytes?

  • From a string:

    message = "Hello"
    encoded = message.encode("utf-8")
  
  • Using a literal:
raw = b"data"
  • From a list of integers:

    values = bytes([65, 66, 67])
    print(values)  # b'ABC'
  

Where is it Used?

  • Working with binary files (rb/wb);
  • Network protocols and sockets;
  • Serialization and decoding data;
  • Encryption and hashing (hashlib, base64);
  • APIs that require "bytes, not strings".

Important Methods

  • .decode() — converts bytes back to a string:
text = b"Hello".decode("utf-8")
  • .hex() — hexadecimal string representation:
b"Hi".hex()  # '4869'

What is Bytearray?

bytearray is a mutable array of bytes. It contains the same values as bytes (from 0 to 255), but allows modifying the content after creation. This makes it useful for operations where binary data needs to be built or modified incrementally.


    data = bytearray(b"abc")
    data[0] = 65
    print(data)  # bytearray(b'Abc')
  

How to Create a Bytearray?

  • From a string:
ba = bytearray("text", "utf-8")
  • From bytes:
ba = bytearray(b"data")
  • From a list of integers:
ba = bytearray([1, 2, 3, 255])

Bytearray Capabilities

  • Modifying individual bytes:
ba[1] = 88
  • Appending:
ba.append(33)  # adds byte with code 33
  • Extending:
ba.extend(b" more")
  • Deleting:
del ba[0]
  • Converting to bytes:
b = bytes(ba)

Where is it Used?

  • Data buffers in network programming;
  • Incremental packet building for transmission;
  • High-performance scenarios where write speed is crucial.

What is Memoryview?

memoryview is a view object over other binary structures (bytes, bytearray, array.array). It allows accessing data without copying, which is especially important for large data volumes or memory-constrained environments.


    b = bytearray(b"abcdef")
    view = memoryview(b)
    print(view[1])       # 98 (code for 'b')
  

memoryview creates a window into memory without duplicating content, providing higher performance.

Advantages

  • No extra memory copying;
  • Can access parts of data (slices);
  • Convenient for binary streams, files, buffers, images.

How to Use?


    data = bytearray(b"hello world")
    view = memoryview(data)

    # byte access
    print(view[0])  # 104

    # modifying content
    view[0] = 72
    print(data)  # bytearray(b'Hello world')
  

Supports Slices


    part = view[0:5]
    print(part.tobytes())  # b'Hello'
  

Where is it Used?

  • In the struct library for packing/unpacking data;
  • For processing video/audio streams;
  • In image processing and NumPy libraries;
  • In network and file operations with no speed loss.

Common Beginner Mistakes

Working with binary types requires understanding the difference between strings and bytes, as well as each type's specific features. Below are the most common mistakes that hinder beginners from using bytes, bytearray, and memoryview effectively.

1. Using a regular string instead of bytes

f.write("hello")  # TypeError in 'wb' mode

Explanation: When working with binary files, you must use bytes, not str.

Solution:


    f.write(b"hello")
    # or
    f.write("hello".encode("utf-8"))
  

2. Trying to modify a bytes object


    data = b"abc"
    data[0] = 65  # TypeError
  

Solution: Use bytearray for a mutable version:


    data = bytearray(b"abc")
    data[0] = 65
  

3. Incorrect string conversion

data = bytes("abc")  # TypeError: string argument without an encoding

Solution:

data = bytes("abc", "utf-8")

4. Misunderstanding memoryview structure


    view = memoryview(b"data")
    view[0] = 100  # TypeError: cannot modify read-only memory
  

Solution:
You can only modify memoryview over mutable objects (bytearray, array.array), not over bytes.

5. Ignoring Byte Range

ba = bytearray([300])  # ValueError

Solution: All values must be from 0 to 255:

ba = bytearray([255])

Frequently Asked Questions

What is the difference between bytes and bytearray in Python?

bytes is an immutable sequence of bytes. Once created, the object cannot be modified: any attempts to change a byte or add a value will result in an error. This makes bytes a safe type for transmitting data, serialization, and storage.

bytearray, by contrast, is mutable. You can modify its contents: replace, add, or delete bytes. It is used when data is built step-by-step or needs to be changed during runtime.

If you are working with network buffers, binary streams, or low-level I/O, bytearray is preferred. If the data should remain constant, use bytes.

How do I convert a string to a bytes object?

To properly convert a string (str) to a bytes object, you need to specify the encoding. The most common choice is utf-8. A simple call to bytes("abc") will raise an error because the interpreter doesn't know how to interpret the string.

The correct way:


      s = "hello"
      b = s.encode("utf-8")

The .encode() method creates a byte representation of the string. It can be passed to a file, sent over a network, or processed at a low level. You can also use bytes("hello", "utf-8"). The reverse conversion is done via .decode().

When should I use memoryview?

Use memoryview when working with large amounts of binary data and you want to access parts of the data without copying it. This is important for saving memory and improving performance. memoryview allows modifying data (if the underlying object is a bytearray) or safely reading it (if it's a bytes object).

Examples include: stream buffering, accessing image segments, working with mmap files, and network packets. It is also used in libraries like NumPy, Pillow, and struct.

If you are working with byte slices and want to avoid data duplication, use memoryview.

Can I read and write binary files using binary types?

Yes. When working with binary files, always open them with the "rb" (read binary) or "wb" (write binary) flag. In this mode, you can only read and write bytes objects, not str.

Example of writing:


    with open("file.bin", "wb") as f:
      f.write(b"ABC")

Example of reading:


    with open("file.bin", "rb") as f:
      content = f.read()

If you need to work with mutable data, use bytearray(content) to modify it and then write it back. Always check your types—errors most often occur when trying to write a string to a binary file.

What is the byte range allowed in bytes and bytearray?

All elements in bytes and bytearray must be integers between 0 and 255. This is because a single byte can only store values in that range.

Example:

b = bytes([0, 127, 255])

Attempting to use a number outside this range will raise a ValueError. This often happens when trying to add a "normal" number without validation, especially from external data.

Therefore, it's important to validate incoming values in advance or use methods that prevent exceeding byte limits (e.g., int.to_bytes() with controlled length).