A game without saves is like a zombie apocalypse without a shelter: everything is lost! 😱
Learn to write data to files and read it back with with open — the proper way to handle files in Python.
🤔 Why do we need files?
The problem: data disappears
class Human:
def __init__(self, name):
self.name = name
self.kills = 0
rick = Human("Rick")
rick.kills = 10
# Close the program...
# ...open it again
# Data is gone! 😱
Solution: Save to a file!
# Write to a file
with open("saves/rick.txt", "w") as f:
f.write(f"{rick.name}\n")
f.write(f"{rick.kills}\n")
# Close the program...
# ...open it again
# Read from the file
with open("saves/rick.txt", "r") as f:
name = f.readline().strip()
kills = int(f.readline().strip())
print(f"{name}: {kills} kills") # Rick: 10 kills ✅
📝 Writing to a file: "w" mode
Syntax
with open("filename.txt", "w") as f:
f.write("text")
"w" = write. Creates a new file or overwrites an existing one!
Example 1: Battle log
with open("battle_log.txt", "w") as f:
f.write("=== BATTLE LOG ===\n")
f.write("Rick attacks Walker\n")
f.write("Damage: 20\n")
f.write("Zombie defeated!\n")
# battle_log.txt now contains:
# === BATTLE LOG ===
# Rick attacks Walker
# Damage: 20
# Zombie defeated!
Example 2: Saving stats
class Human:
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}!")
rick = Human("Rick")
rick.kills = 5
rick.save()
# Created saves/Rick.txt with the data
📖 Reading from a file: "r" mode
Syntax
with open("filename.txt", "r") as f:
content = f.read() # Read entire file
"r" = read.
Reading methods
1. read() — read the whole file at once
with open("battle_log.txt", "r") as f:
content = f.read()
print(content)
# Prints the entire file as one string
2. readline() — read one line
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")
strip() removes the trailing \n (newline character).
3. readlines() — read all lines into a list
with open("battle_log.txt", "r") as f:
lines = f.readlines() # ['=== BATTLE LOG ===\n', 'Rick attacks...\n', ...]
for line in lines:
print(line.strip()) # Print each line
Example: Loading a character
class Human:
def __init__(self, name):
self.name = name
self.kills = 0
self.health = 100
@staticmethod
def load(name):
"""Load a character from a file."""
with open(f"saves/{name}.txt", "r") as f:
loaded_name = f.readline().strip()
kills = int(f.readline().strip())
health = int(f.readline().strip())
# Create an object with the loaded data
human = Human(loaded_name)
human.kills = kills
human.health = health
print(f"Loaded {loaded_name}!")
return human
# Usage
rick = Human.load("Rick")
print(f"{rick.name}: {rick.kills} kills, {rick.health} HP")
➕ Appending to a file: "a" mode
"a" = append. Does NOT overwrite — it adds to the end!
# First write
with open("kills.txt", "w") as f:
f.write("Kills:\n")
# Append new entries
with open("kills.txt", "a") as f:
f.write("Rick killed Walker\n")
f.write("Daryl killed Runner\n")
# Append another entry later
with open("kills.txt", "a") as f:
f.write("Michonne killed Tank\n")
# File now contains:
# Kills:
# Rick killed Walker
# Daryl killed Runner
# Michonne killed Tank
Example: Battle logger
class BattleLogger:
def __init__(self, filename):
self.filename = filename
# Create the file with a header
with open(self.filename, "w") as f:
f.write("=== BATTLE LOG ===\n\n")
def log(self, message):
# Append to the end of the file
with open(self.filename, "a") as f:
f.write(f"{message}\n")
logger = BattleLogger("battle.txt")
logger.log("Rick attacks Walker (damage: 20)")
logger.log("Walker defeated!")
logger.log("Daryl shoots Runner (damage: 50)")
🔒 Why use with?
❌ Old way (without with):
f = open("data.txt", "w")
f.write("Data")
f.close() # ← Easy to forget!
Problems:
- ❌ You can forget to call .close()
- ❌ If an exception occurs, the file won’t be closed
- ❌ Resource leak
✅ The right way (with with):
with open("data.txt", "w") as f:
f.write("Data")
# File closes automatically!
Benefits:
- ✅ File closes automatically (even if an exception occurs)
- ✅ Shorter and clearer
- ✅ Safer
📊 File open modes
| Mode | Name | Behavior | If file doesn’t exist |
|---|---|---|---|
"r" |
read | Read only | Error |
"w" |
write | Write (overwrites) | Creates new file |
"a" |
append | Add to end | Creates new file |
"r+" |
read+write | Read and write | Error |
"w+" |
write+read | Write and read (overwrites) | Creates new file |
Most common: "r", "w", "a"
🎮 Full example: Game with saves
class Game:
def __init__(self):
self.player_name = ""
self.level = 1
self.kills = 0
self.health = 100
def new_game(self, name):
"""Start a new game."""
self.player_name = name
self.level = 1
self.kills = 0
self.health = 100
print(f"New game started: {name}")
def save_game(self):
"""Save the game."""
filename = f"saves/{self.player_name}_save.txt"
with open(filename, "w") as f:
f.write(f"{self.player_name}\n")
f.write(f"{self.level}\n")
f.write(f"{self.kills}\n")
f.write(f"{self.health}\n")
print(f"✅ Game saved: {filename}")
def load_game(self, name):
"""Load a saved game."""
filename = f"saves/{name}_save.txt"
try:
with open(filename, "r") as f:
self.player_name = f.readline().strip()
self.level = int(f.readline().strip())
self.kills = int(f.readline().strip())
self.health = int(f.readline().strip())
print(f"✅ Game loaded: {filename}")
except FileNotFoundError:
print(f"❌ Save not found: {filename}")
def status(self):
"""Show current status."""
print(f"\n{'='*40}")
print(f"Player: {self.player_name}")
print(f"Level: {self.level}")
print(f"Kills: {self.kills}")
print(f"Health: {self.health}")
print(f"{'='*40}\n")
# Usage
game = Game()
game.new_game("Rick")
game.kills = 10
game.level = 3
game.status()
game.save_game()
# Close the program...
# Open it again
game2 = Game()
game2.load_game("Rick")
game2.status() # Data restored! ✅
⚠️ Common mistakes
Mistake 1: Missing mode
with open("data.txt") as f: # ❌ No mode!
f.write("Data") # Error: not writable
Fix:
with open("data.txt", "w") as f: # ✅ Specified "w"
Mistake 2: Trying to write in "r" mode
with open("data.txt", "r") as f:
f.write("Data") # ❌ UnsupportedOperation: not writable
Fix:
with open("data.txt", "w") as f: # ✅ Use "w" mode
Mistake 3: Forgot .strip() when reading
with open("saves/data.txt", "r") as f:
kills = int(f.readline()) # ❌ '10\n' → conversion error
# Fix:
kills = int(f.readline().strip()) # ✅ '10'
Mistake 4: File not found
with open("saves/data.txt", "r") as f: # ❌ FileNotFoundError
content = f.read()
Fix: Check existence or use try-except:
try:
with open("saves/data.txt", "r") as f:
content = f.read()
except FileNotFoundError:
print("File not found!")
💡 Best practices
✅ Good:
1. Always use with
with open("data.txt", "w") as f: # ✅ Closes automatically
f.write("Data")
2. Organize files in subdirectories
with open("saves/player.txt", "w") as f: # ✅ Organized
3. Use try-except when reading
try:
with open("data.txt", "r") as f:
content = f.read()
except FileNotFoundError:
print("File not found")
4. Always call .strip() on read lines
name = f.readline().strip() # ✅ Removes \n
❌ Bad:
1. Without with
f = open("data.txt", "w") # ❌ Easy to forget close()
f.write("Data")
f.close()
2. Mixing up modes
with open("data.txt", "w") as f:
content = f.read() # ❌ "w" mode doesn't support reading!
📝 Checklist
- [ ] I know why files are needed (persisting data)
- [ ] I understand the
with open(...) as f:syntax - [ ] I know the modes:
"r"(read),"w"(write),"a"(append) - [ ] I can write data:
f.write() - [ ] I can read data:
f.read(),f.readline() - [ ] I understand why
withis needed (auto-close) - [ ] I know to use
.strip()when reading lines - [ ] I know how to handle
FileNotFoundError
🚀 Summary
with open is the correct way to work with files.
Syntax:
# Write
with open("file.txt", "w") as f:
f.write("data")
# Read
with open("file.txt", "r") as f:
content = f.read()
# Append
with open("file.txt", "a") as f:
f.write("more data")
Modes:
- "r" — read
- "w" — write (overwrites existing content)
- "a" — append (adds to the end)
Why with?
- ✅ Closes the file automatically
- ✅ Safer (closes even if an exception occurs)
- ✅ Shorter and more readable
File object methods:
- f.write(text) — write text
- f.read() — read the entire file
- f.readline() — read one line
- f.readlines() — read all lines into a list
Why do we need files?
To save progress, logs, and statistics — anything that must survive closing the program! 💾
Next step: Use files inside classes to persist objects! 🎮
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!