Web Analytics

Writing Files

Intermediate ~25 min read

Creating and writing files is essential for saving program output, generating reports, logging events, and persisting data. Python provides intuitive methods for writing text and binary files. Understanding the difference between write mode ('w') which overwrites and append mode ('a') which adds to existing content is crucial - choosing wrong can destroy your data!

Write Modes

The mode parameter in open() determines how files are created and written. Write mode ('w') creates a new file or completely overwrites an existing one - all previous content is lost! Append mode ('a') is safer when you want to add to existing content. Exclusive create mode ('x') prevents accidental overwrites.

Output
Click Run to execute your code
Danger Zone! Write mode ('w') destroys existing content without warning! If you open an important file in write mode, all its data is gone the moment you call open() - even before you write anything. Always double-check your mode when working with existing files.

Write Methods

Python provides two main methods for writing: write() writes a single string and returns the number of characters written, while writelines() writes a list of strings. Important: neither method adds newlines automatically - you must include \n yourself!

Output
Click Run to execute your code
write() vs writelines():
write(string) - Writes one string, returns character count
writelines(list) - Writes list of strings, returns None
Neither adds newlines! You must include \n in your strings.
For large data, writelines() with a generator is memory-efficient.

Writing Binary Files

Binary mode ('wb') writes raw bytes instead of text. This is essential for images, audio, compressed files, and any non-text data. You must write bytes or bytearray objects, not strings. Use encode() to convert strings to bytes, or the struct module for structured binary data.

Output
Click Run to execute your code
When to Use Binary Mode:
- Images (PNG, JPEG, GIF)
- Audio/Video files
- Compressed archives (ZIP, GZIP)
- Executables and compiled code
- Network protocols and serialized data
- Any file where exact byte representation matters

Formatted File Output

Often you need to write formatted data - tables, reports, or structured text. Python offers several ways to format output: f-strings for inline formatting, format() for templates, and even print() with the file parameter. For efficiency with many lines, join them into one string before writing.

Output
Click Run to execute your code

Common Mistakes

1. Accidentally overwriting important files

# DISASTER - overwrites config file!
with open("config.txt", "w") as f:
    f.write("debug=true")  # Lost all other settings!

# Safe approach - read first, modify, write back
with open("config.txt", "r") as f:
    content = f.read()
# Modify content...
with open("config.txt", "w") as f:
    f.write(modified_content)

# Or use append mode to add settings
with open("config.txt", "a") as f:
    f.write("\ndebug=true")

2. Forgetting newlines with writelines()

# Wrong - creates one long line!
lines = ["apple", "banana", "cherry"]
with open("fruits.txt", "w") as f:
    f.writelines(lines)  # Result: "applebananacherry"

# Correct - add newlines
lines = ["apple\n", "banana\n", "cherry\n"]
with open("fruits.txt", "w") as f:
    f.writelines(lines)

# Or use generator expression
lines = ["apple", "banana", "cherry"]
with open("fruits.txt", "w") as f:
    f.writelines(line + "\n" for line in lines)

3. Writing strings to binary files

# Wrong - TypeError: a bytes-like object is required
with open("data.bin", "wb") as f:
    f.write("Hello")  # Error!

# Correct - encode string to bytes
with open("data.bin", "wb") as f:
    f.write("Hello".encode("utf-8"))

# Or use bytes literal
with open("data.bin", "wb") as f:
    f.write(b"Hello")

4. Not flushing or closing files

# Wrong - data may not be written yet!
f = open("log.txt", "w")
f.write("Important data")
# Program crashes here - data may be lost!

# Correct - use 'with' statement
with open("log.txt", "w") as f:
    f.write("Important data")
# Automatically closed and flushed

# Or manually flush for long-running programs
f = open("log.txt", "w")
f.write("Log entry")
f.flush()  # Force write to disk now

5. Writing many small strings inefficiently

# Slow - many small write calls
with open("output.txt", "w") as f:
    for i in range(10000):
        f.write(f"Line {i}\n")  # 10000 write calls!

# Fast - build string first, single write
lines = [f"Line {i}" for i in range(10000)]
with open("output.txt", "w") as f:
    f.write("\n".join(lines))  # One write call!

# Or use writelines with generator
with open("output.txt", "w") as f:
    f.writelines(f"Line {i}\n" for i in range(10000))

Exercise: Log File Writer

Task: Create a simple log file writer that appends timestamped entries.

Requirements:

  • Write a function that appends log entries with timestamps
  • Each entry should be on its own line
  • Include the log level (INFO, WARNING, ERROR)
  • Demonstrate with multiple log entries
Output
Click Run to execute your code
Show Solution
from datetime import datetime
import os

def log_message(filename, level, message):
    """Append a timestamped log entry to a file."""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    entry = f"[{timestamp}] {level}: {message}\n"

    with open(filename, "a") as f:
        f.write(entry)

# Test the logger
log_file = "app.log"

# Write some log entries
log_message(log_file, "INFO", "Application started")
log_message(log_file, "INFO", "User logged in: alice")
log_message(log_file, "WARNING", "Low memory: 85% used")
log_message(log_file, "ERROR", "Database connection failed")
log_message(log_file, "INFO", "Retrying connection...")
log_message(log_file, "INFO", "Connection restored")

# Read and display the log
print("=== Log Contents ===")
with open(log_file, "r") as f:
    print(f.read())

# Cleanup
os.remove(log_file)

Summary

  • Write mode: open("file", "w") - overwrites existing content
  • Append mode: open("file", "a") - adds to end of file
  • Exclusive create: open("file", "x") - fails if file exists
  • Write string: f.write("text") - returns char count
  • Write list: f.writelines(["a", "b"]) - no auto newlines!
  • Binary write: open("file", "wb") with bytes
  • Print to file: print("text", file=f)
  • Force flush: f.flush() - writes buffer to disk
  • Always use: with open(...) as f: for auto-close
  • Efficiency: Join strings before writing for better performance

What's Next?

Now that you can read and write files, let's learn about context managers - the Pythonic way to handle resources. The with statement ensures files are properly closed even when errors occur, and you can create your own context managers for other resources!