The file.write(data) method writes a string (in text mode) or bytes object (in binary mode) to an open file stream, returning the exact count of characters or bytes written.
Safe Resource Management: Always invoke write() inside a with open(...) as f: context manager. When the block exits, Python automatically flushes buffered output and safely closes the OS file descriptor.
The standard CPython signature for file.write() is:
file_object.write(data)
| Component | Type | Required? | Behavior & Description |
|---|---|---|---|
data |
str or bytes-like |
Yes | In text mode, must be a str. In binary mode ('wb', 'ab'), must be a bytes or bytearray. Passing non-string objects (like integers or lists) raises TypeError. |
| Return Value | int |
— | The number of characters (in text mode) or bytes (in binary mode) successfully written to the stream. |
| Exceptions | IOError / PermissionError |
— | Raised on disk quota exhaustion, read-only filesystems, or insufficient write permissions. |
Selecting the correct file mode prevents accidental data loss and ensures thread-safe or process-safe file operations:
| Mode | Pointer Position | If File Exists | If File Missing | Primary Engineering Role |
|---|---|---|---|---|
'w' |
Beginning (offset 0) | Truncates immediately (erases content) | Creates new file | Overwriting logs, saving freshly generated reports. |
'a' |
End of file (EOF) | Preserves data; writes append to end | Creates new file | Appending log events, audit records, event streams. |
'x' |
Beginning (offset 0) | Raises FileExistsError |
Creates new file | Safe creation avoiding accidental file overwrite. |
'r+' |
Beginning (offset 0) | Preserves data; in-place overwriting | Raises FileNotFoundError |
In-place binary patching, database header updates. |
'wb' |
Beginning (offset 0) | Truncates immediately | Creates new file | Saving binary downloads, images, compiled artifacts. |
In older Python code, developers relied on explicit fob.close() calls. If an unhandled exception occurred between open() and close(), data remained in memory buffers uncommitted to disk. The with statement eliminates this risk completely:
# Open in write mode ('w') with explicit UTF-8 encoding
with open("summary.txt", "w", encoding="utf-8") as fob:
fob.write("Python File Handling Overview\n")
fob.write("==============================\n")
fob.write("All buffered data is flushed on block exit.\n")
# Verified: the stream is closed immediately outside the block
print("Is stream closed?", fob.closed) # True
Starting in Python 3, file.write() returns an integer representing the exact count of characters or bytes written. This return value allows data pipelines to verify write integrity:
message = "Hello, plus2net Python learners!\n"
with open("output.txt", "w", encoding="utf-8") as f:
written_count = f.write(message)
print(f"Characters requested: {len(message)}")
print(f"Characters written: {written_count}")
assert written_count == len(message)
To maximize I/O throughput, Python buffers writes in memory before dispatching them to the operating system. If power cuts or process crashes occur before buffer exhaustion, un-flushed data may be lost.
import os
with open("critical_audit.log", "a", encoding="utf-8") as log_file:
log_file.write("Transaction ID 98402: SUCCESS\n")
# 1. Flush Python internal user-space buffer to OS buffer
log_file.flush()
# 2. Force OS buffer to commit directly to physical storage device
os.fsync(log_file.fileno())
When saving images, compressed data, network packets, or audio streams, open files with mode 'wb'. Binary streams require bytes or bytearray arguments and do not perform platform-specific newline transformations:
# Construct raw binary payload (e.g. 4-byte magic number + binary data)
magic_bytes = bytes([0x7F, 0x45, 0x4C, 0x46]) # ELF binary header
with open("artifact.bin", "wb") as bin_file:
bytes_written = bin_file.write(magic_bytes)
print("Bytes written to binary stream:", bytes_written)
Writing directly to an existing file with mode 'w' immediately wipes existing contents. If your application crashes mid-write, the file is corrupted. In production architectures, write to a temporary file in the same filesystem directory and rename it atomically via os.replace():
import tempfile
import os
def atomic_write_file(target_path: str, content: str, encoding: str = "utf-8") -> None:
target_dir = os.path.dirname(target_path) or "."
# Write to temp file on the same filesystem
with tempfile.NamedTemporaryFile("w", dir=target_dir, delete=False, encoding=encoding) as tf:
tf.write(content)
temp_name = tf.name
# Atomic replacement on POSIX and Windows
os.replace(temp_name, target_path)
atomic_write_file("app_config.json", '{"status": "ready", "version": 2}')
print("Configuration safely saved with zero risk of partial file corruption.")
Unlike print(), file.write() writes exactly the text provided without appending a newline (
). Consecutive writes will run together on the same line unless you explicitly include
.
with open("names.txt", "w", encoding="utf-8") as f:
f.write("Alex")
f.write("Ronald")
# Resulting file content is: "AlexRonald" (no space, no newline)
# Correct pattern:
with open("names.txt", "w", encoding="utf-8") as f:
f.write("Alex\n")
f.write("Ronald\n")
Passing numbers, dictionaries, or lists directly to write() raises TypeError: write() argument must be str, not int. Convert numbers to strings with str() or use formatted string literals (f-strings).
Execute this self-contained test harness verifying write modes, return counts, binary operations, and atomic persistence:
import tempfile
import os
class FileWriterVerifier:
@staticmethod
def write_text(path: str, data: str) -> int:
with open(path, "w", encoding="utf-8") as stream:
return stream.write(data)
@staticmethod
def append_text(path: str, data: str) -> int:
with open(path, "a", encoding="utf-8") as stream:
return stream.write(data)
@staticmethod
def write_binary(path: str, data: bytes) -> int:
with open(path, "wb") as stream:
return stream.write(data)
# Verification unit assertions
with tempfile.TemporaryDirectory() as td:
v = FileWriterVerifier()
sample_file = os.path.join(td, "test.txt")
# Test 1: Write returns character count
assert v.write_text(sample_file, "Hello") == 5
# Test 2: Append mode preserves previous text
assert v.append_text(sample_file, " World") == 6
with open(sample_file, "r", encoding="utf-8") as f:
assert f.read() == "Hello World"
# Test 3: Binary write verification
bin_file = os.path.join(td, "test.bin")
assert v.write_binary(bin_file, b" ÿª") == 3
# Test 4: Exclusive mode raises FileExistsError
try:
with open(sample_file, "x", encoding="utf-8") as f:
f.write("conflict")
assert False, "FileExistsError expected"
except FileExistsError:
pass
print("All file.write() unit assertions passed successfully!")
Open in Google Colab View on GitHub
Run all file write exercises interactively, test 'w' vs 'a' vs 'x' modes, inspect return character counts, practice atomic file replacement, and write raw binary byte buffers in Google Colab.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.