HOWTO · Python
How to Write Bytes to a File in Python
This tutorial demonstrates how to write bytes to a binary file in Python. Learn different methods, including using the open function, writing multiple bytes, utilizing bytearrays, and buffering techniques. Discover practical code examples and detailed explanations to enhance your skills in handling binary data effectively.
On this page
To write bytes to a file in Python, call open() with the mode wb and pass a bytes-like object to the file’s write() method. Use a with block to close the file automatically. Choose ab instead when you want to append to existing contents.
Each code example creates its files in a temporary directory. Python removes that directory when the example’s with block ends. To keep a file, replace its temporary path with your destination.
How to Write Bytes to a File in Python
The w in wb opens a file for writing: it creates the file if needed and truncates an existing file as soon as it opens. The b selects binary mode, so Python writes bytes without text encoding or newline translation.
Run this example to write data and read it back:
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "example.bin"
data = b"This is some binary data."
with open(path, "wb") as file:
written = file.write(data)
with open(path, "rb") as file:
saved = file.read()
print(written)
print(saved == data)
25
True
For this regular buffered file, write() returns the number of bytes written. The program prints that count and compares the saved data with the original. Reading happens after the writing block closes the file and flushes its Python buffer. A .bin extension is a naming convention; binary mode comes from the mode argument.
Use xb if you want to create a file only when it does not already exist. Unlike wb, it refuses to overwrite an existing destination. Neither mode creates missing parent directories.
Write Multiple Byte Sequences to a File
Keep the file open while writing successive chunks. Each write() continues at the current position; opening the file with wb inside the loop would discard earlier chunks.
from pathlib import Path
from tempfile import TemporaryDirectory
chunks = [b"First line.\n", b"Second line.\n", b"Third line.\n"]
with TemporaryDirectory() as directory:
path = Path(directory) / "chunks.bin"
with open(path, "wb") as file:
for chunk in chunks:
file.write(chunk)
Each chunk must be bytes-like data, such as bytes, bytearray, or a suitable buffer view. You can also pass an iterable of byte sequences to file.writelines(chunks). Despite its name, writelines() adds no separators or newlines; include them in the chunks when required. A loop also lets you consume chunks as they arrive without joining the entire payload in memory.
Write a bytearray to a File
A bytes object is immutable, while a bytearray lets you change individual bytes or extend the sequence before saving it. Both can be written directly to a binary file.
from pathlib import Path
from tempfile import TemporaryDirectory
payload = bytearray(b"Line 1\n")
payload.extend(b"Line 2\n")
payload[0] = ord("l")
with TemporaryDirectory() as directory:
path = Path(directory) / "bytearray.bin"
with open(path, "wb") as file:
file.write(payload)
Here, extend() adds another sequence and the indexed assignment changes the first byte. You do not need bytes(payload) for the write; use that conversion when you need an immutable value elsewhere. Later changes to the bytearray do not update the file automatically.
Write BytesIO Data to a File
BytesIO, from the io module, provides an in-memory binary stream. Its getbuffer() method returns a view of the entire underlying buffer without copying its contents into a separate bytes object.
from io import BytesIO
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "buffer.bin"
with BytesIO() as buffer:
buffer.write(b"Header\n")
buffer.write(b"Payload\n")
with buffer.getbuffer() as view:
with open(path, "wb") as file:
file.write(view)
The view covers all buffered data regardless of the stream’s current position. While the view exists, the BytesIO object cannot be resized or closed; the nested context managers release it before closing the stream. Use buffer.getvalue() when you want a bytes value instead. To copy with buffer.read(), first call buffer.seek(0) if you need to start from the beginning.
Append Bytes or Write at a Position
Open with ab to add bytes at the end without truncating existing contents. This mode also creates the destination if it does not exist. To overwrite bytes at a particular offset in an existing file, use r+b and the file object’s seek() method.
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "records.bin"
with open(path, "wb") as file:
file.write(b"ABCDEF")
with open(path, "ab") as file:
file.write(b"GH")
with open(path, "r+b") as file:
file.seek(2)
file.write(b"xy")
seek(2) moves to byte offset 2, counting from the beginning. The next write replaces two bytes without inserting data or removing the remaining tail. Use truncate() explicitly if you need to remove trailing bytes after a shorter replacement.
r+b requires an existing file and preserves its contents when opened. w+b allows reading and writing but truncates the file first. Avoid append mode for positioned updates: writes are directed to the end, and seeking is not a portable way to override that behavior. Seeking past the end alone does not extend a file; a subsequent write can extend it, with gap storage details depending on the filesystem.
Buffering and Large Writes
Regular binary files opened with open() are buffered by default. An explicit setting such as buffering=8192 requests a buffer size; it does not guarantee faster writes or force each operating-system write to contain exactly 8192 bytes.
For large generated data, write reusable chunks rather than constructing one large combined object:
from pathlib import Path
from tempfile import TemporaryDirectory
chunk = b"record\n" * 1024
with TemporaryDirectory() as directory:
path = Path(directory) / "large.bin"
with open(path, "wb", buffering=8192) as file:
for _ in range(100):
file.write(chunk)
This example demonstrates an optional buffer setting and reuses one chunk. Choose buffer sizes through measurements of your actual workload; there is no universally best size. Closing the file flushes Python’s buffer. Calling flush() earlier transfers buffered data to the underlying stream, but does not by itself guarantee persistence on physical storage.
Common Questions About Writing Bytes
How do I read the bytes back? Open the file with rb and call file.read(). The returned value is bytes. For a large file, read fixed-size chunks instead of loading everything at once.
Can I write text in binary mode? Encode it first, for example with text.encode("utf-8") or bytes(text, "utf-8"). The reader must use the corresponding encoding to recover the text. If your task is purely text storage, opening in text mode with encoding="utf-8" may be clearer.
Why does write() report a TypeError? A binary stream requires bytes-like data. Passing a str, an integer, or a list directly does not satisfy that requirement. Encode text, or convert a sequence of integer byte values with bytes(values); each integer must be in the range 0 through 255.
What happens with an empty payload? Writing b"" writes no bytes, but opening an existing file with wb has already truncated it. Use ab to preserve existing data when appending, including when the new payload is empty.
Why was the destination not created? Check that its parent directory exists and that the process has permission to write there. A relative path is resolved from the process’s current working directory. Handle relevant OSError failures in application code, and remember that a write or close can still fail after the file opens successfully.