๐Ÿ“ Python

with open: Working with Files the Right Way

P
Author
PyLand Team
๐Ÿ“…
Published
03.04.2026
โฑ๏ธ
Reading time
2 min
๐Ÿ‘๏ธ
Views
385
๐ŸŒฟ
Level
Medium

Files preserve data between program runs, while the with statement ensures that a file is closed correctly even when an error occurs.

Why Do We Need Files?

Data in variables only lives while the program runs. When it closes โ€” everything is lost.

# Without a file: data disappears when the program closes
score = 100
player = "Rick"

# With a file: data persists between runs
with open("save.txt", "w") as f:
    f.write(f"{player}\n{score}\n")

without vs with: Why the Context Manager Matters

# Old way โ€” easy to forget to close the file
f = open("data.txt", "w")
f.write("Data")
f.close()  # If an error occurs before this โ€” the file won't be closed!

# Correct way โ€” with closes the file automatically
with open("data.txt", "w") as f:
    f.write("Data")
# File is closed here, even if an error occurred inside

Mode “w” โ€” Write

with open("battle_log.txt", "w") as f:
    f.write("=== BATTLE LOG ===\n")
    f.write("Rick attacks Walker\n")
    f.write("Damage: 20\n")

Note: mode "w" overwrites the file completely on each open.

class Player:
    def __init__(self, name):
        self.name = name
        self.kills = 0
        self.health = 100

    def save(self):
        with open(f"saves/{self.name}.txt", "w") as f:
            f.write(f"{self.name}\n")
            f.write(f"{self.kills}\n")
            f.write(f"{self.health}\n")
        print(f"Saved: {self.name}")

player = Player("Rick")
player.kills = 5
player.save()

Mode “r” โ€” Read

with open("saves/Rick.txt", "r") as f:
    content = f.read()       # Entire file as a string
    print(content)

Reading Methods

with open("saves/Rick.txt", "r") as f:
    name   = f.readline().strip()   # First line
    kills  = f.readline().strip()   # Second line
    health = f.readline().strip()   # Third line

print(f"{name}: {kills} kills, {health} HP")
with open("battle_log.txt", "r") as f:
    lines = f.readlines()  # List of lines

for line in lines:
    print(line.strip())

strip() removes the \n character at the end of each line.

class Player:
    @staticmethod
    def load(name):
        with open(f"saves/{name}.txt", "r") as f:
            loaded_name = f.readline().strip()
            kills  = int(f.readline().strip())
            health = int(f.readline().strip())

        p = Player(loaded_name)
        p.kills  = kills
        p.health = health
        return p

rick = Player.load("Rick")
print(f"{rick.name}: {rick.kills} kills, {rick.health} HP")

Mode “a” โ€” Append

Mode "a" adds to the end of the file without deleting existing content:

with open("log.txt", "w") as f:
    f.write("Log started\n")

# Later, add events
with open("log.txt", "a") as f:
    f.write("Rick killed Walker\n")

with open("log.txt", "a") as f:
    f.write("Daryl killed Runner\n")

# File:
# Log started
# Rick killed Walker
# Daryl killed Runner

Mode Table

Mode What it does If file doesn’t exist
"r" Reads Error
"w" Writes (overwrites) Creates
"a" Appends to end Creates

Common Mistakes

Mistake 1: Forgot the Mode

# โŒ Default is "r" โ€” can't write
with open("data.txt") as f:
    f.write("Data")  # UnsupportedOperation: not writable

# โœ… Always specify the mode explicitly
with open("data.txt", "w") as f:
    f.write("Data")

Mistake 2: File Not Found

# โŒ File doesn't exist
with open("saves/data.txt", "r") as f:
    content = f.read()  # FileNotFoundError

# โœ… Handle the error
try:
    with open("saves/data.txt", "r") as f:
        content = f.read()
except FileNotFoundError:
    print("File not found โ€” starting fresh")
    content = ""

Custom Context Manager

with works with any object that implements __enter__ and __exit__:

class Timer:
    import time

    def __enter__(self):
        import time
        self.start = time.time()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        import time
        elapsed = time.time() - self.start
        print(f"Elapsed time: {elapsed:.3f}s")
        return False  # False โ€” don't suppress exceptions

with Timer():
    total = sum(range(1_000_000))
# Elapsed time: 0.031s

__enter__ runs when entering the with block, __exit__ runs on exit (including on error).

Your reaction to the article

๐Ÿ’ฌ Comments (0)

๐Ÿ” Sign in to leave a comment
๐Ÿšช Login
๐Ÿ’ญ

No comments yet

Be the first to share your opinion about this article!

๐Ÿ”— Similar

Similar articles

Continue learning with these materials

๐Ÿ“

if __name__ == "__main__": the Python entry point

The if name == "main" guard defines a Python program's entry point: it distinguishes direct...

๐Ÿ“… 14.08.2026 ๐Ÿ‘๏ธ 44
๐Ÿ“

strip() and lower(): Preparing User Text ๐Ÿงน

A user may enter the correct word with extra spaces or different letter case. Python...

๐Ÿ“… 11.08.2026 ๐Ÿ‘๏ธ 50
๐Ÿ“

ord(), chr(), and Cyclic Letter Shifts in Python ๐Ÿ”

A string contains characters, but a computer stores every character as a numeric code. Python...

๐Ÿ“… 09.08.2026 ๐Ÿ‘๏ธ 89