← Back to course
Code Crew G6+ / Week 09 / Friday
5/6
Week 09 Β· Structured data

Friday

The very first run
// Saving lists and dictionaries with JSON
⏱ about 30 min

Friday: The very first run

Rocket gives his favorite planet tracker to a new crew member. She runs it, and it stops at once with FileNotFoundError.

"It works on my computer," Rocket says, confused. Then he realizes why. "Oh. My computer already has the file."

Raven nods. "What do you notice?" she asks. "Every program that loads a file needs a plan for the first run, when there is nothing to load yet."

Nova shows two paths: a file that exists, and an empty starting point. "Would you like a hint?" she asks. "Check whether the file exists first. If it does not, start with empty data. The first save will make the file."

Rocket imports one more module: os.

Load or start fresh

The os module lets a program ask questions about files. The test os.path.exists("stats.json") is True if that file is in the folder.

The pattern: if the file exists, load it. Otherwise, start with empty data. Either way, save at the end. Next week you will meet another way to do this, with try and except.

# planet_tally.py
import json
import os

FILE = "stats.json"

def load_stats():
    """Load saved stats, or start fresh on the first run."""
    if os.path.exists(FILE):
        with open(FILE) as f:
            return json.load(f)
    return {"runs": 0, "favorites": {}}

def save_stats(stats):
    with open(FILE, "w") as f:
        json.dump(stats, f, indent=2)

stats = load_stats()
stats["runs"] = stats["runs"] + 1
planet = input("Favorite planet today: ").strip().title()
favorites = stats["favorites"]
favorites[planet] = favorites.get(planet, 0) + 1
save_stats(stats)

print(f"Run number {stats['runs']}")
for name, count in favorites.items():
    print(f"{name}: {count}")

.title() makes the first letter of each word a capital and the rest small, so mars, MARS and Mars all count together. Three runs in a row:

Favorite planet today: Mars
Run number 1
Mars: 1
Favorite planet today: venus
Run number 2
Mars: 1
Venus: 1
Favorite planet today:   MARS 
Run number 3
Mars: 2
Venus: 1
On the very first run, what does load_stats give back for "runs"?
A fourth run with the answer venus. What is shown for Venus?
FIRST RUNS
  • Read the question.
  • Tap your answer.
Which line creates stats.json on the very first run?
At your computer
1. Type planet_tally.py, save it in your mission folder and run it three times.
2. Open stats.json in IDLE and read it.
3. Rename stats.json to old_stats.json in your file browser. Run the program again. It starts fresh.
4. Ask a grown-up for their favorite planet and add it.

Practice: a launch counter

This short program remembers how many times it has run. On the very first run there is no file, so it starts from zero.

# launch_counter.py
import json
import os

FILE = "launches.json"
if os.path.exists(FILE):
    with open(FILE) as f:
        data = json.load(f)
else:
    data = {"launches": 0}

data["launches"] = data["launches"] + 1
with open(FILE, "w") as f:
    json.dump(data, f)
print("Launches so far:", data["launches"])
FIRST RUN AND AFTER
  • Read the question.
  • Tap your answer.
What does the very first run show?
What does launches.json hold after two runs?
Why is there no indent in this json.dump?
After five runs, what number shows?
You delete launches.json and run it. What number shows?
What does os.path.exists give when the file is missing?
StatementTrue or false?
os.path.exists checks whether a file is there.?
json.load on a missing file gives a FileNotFoundError.?
The first run should always fail so you know to make a file.?
Saving at the end creates the file if it is missing.?
WHY THIS EXERCISEChecking first and saving at the end lets the first run start fresh and create the file.

Your programs now handle the first run gracefully. That is the last piece Mission Log needs for saving. Tomorrow is a Crew Quest.

← Thursday