← Back to Blog

Calories Tracker Project — Round 7/7

Round 7. The round of refinement. Not what we need — what makes the difference.

Winston Churchill, during some of the most critical moments of the Second World War, said: we do this not because it is easy, but because it is hard. Here it's a demonstration of capability. We do it because we can and we know how.

The structure doesn't change. Only print_general() — and we rename it too. For anyone who reads this code in the future, the name should tell them what the function does. export_general() is more honest than print_general(). A future analyst of our code will thank us.

import datetime
food_dict = {}

# def load_from_txt(): [...]
# def add_food_item(): [...]
# def last_days_details(): [...]
# def print_details(): [...]
# def last_days_sum(): [...]
# def print_target(): [...]
# def general_report(): [...]
# def export_general(): [...]
# load_from_txt()
# while True [...]

The old print_general():

def export_general():
    food_log = general_report()
    for key in sorted(food_log):
        print("=" * 20)
        print(f"Date: {key} - {food_log[key][0]} kcal consumed.")
        print("=" * 20)
        day_dict = food_log[key][1]
        for subkey in sorted(day_dict):
            print(f"Time: {subkey} - {day_dict[subkey][0]}, {day_dict[subkey][1]}{day_dict[subkey][2]} - {day_dict[subkey][3]} kcal.")

Becomes:

def export_general():
    food_log = general_report()

    start_string = min(food_log.keys())
    stop_string  = max(food_log.keys())
    filename = f"report_{start_string}_{stop_string}.txt"

    with open(filename, "w", encoding="utf-8") as f:
        for key in sorted(food_log):
            f.write("=" * 20 + "\n")
            f.write(f"Date: {key} - {food_log[key][0]} kcal consumed.\n")
            f.write("=" * 20 + "\n")
            day_dict = food_log[key][1]
            for subkey in sorted(day_dict):
                f.write(f"Time: {subkey} - {day_dict[subkey][0]}, {day_dict[subkey][1]}{day_dict[subkey][2]} - {day_dict[subkey][3]} kcal.\n")

    print(f"Report saved: {filename}")

filename = f"report_{start_string}_{stop_string}.txt" — the name is built dynamically. start_string and stop_string come from min() and max() on the dictionary keys — the earliest and latest date in the report. If the report covers April 1 through April 7, the file is named report_2025-04-01_2025-04-07.txt. Easy to identify. Easy to archive. Easy to attach to an email.

We use "w" mode — it creates the file if it doesn't exist, and overwrites it if it does. That's intentional. Every export generates a complete, current version of the report for that period. If a file with that name already exists, it gets replaced. Depending on your needs, this could be a limitation — or simply not a problem. We consider it not a problem.

One detail that matters

The structure is mostly the same as add_food_item(). The work wasn't wasted — it never is.

But moving into a new house and giving someone your old address means the package never arrives.

We renamed the function. The menu still needs to know about it. print_general() no longer exists — export_general() does. Option 4 in the menu must reflect that. And print_general() must be removed entirely — a function that's called nowhere and does nothing is noise.

while True:
    option = input("Choose option (1-Add, 2-Show food details, 3-Discipline analysis, 4-General report, q-Quit): ")
    if option == "1":
        add_food_item()
        print("Food log added successfully!")
    elif option == "2":
        if len(last_days_details()):
            print_details()
        else:
            print("No data available.")
    elif option == "3":
        if len(last_days_sum()):
            print_target()
        else:
            print("No data available.")
    elif option == "4":
        if len(general_report()):
            export_general()
        else:
            print("No data available.")
    elif option == "q":
        break
    else:
        print("Invalid option!")

Before you run — a note on test data

Attached to this article is a dummy food_log.txt to experiment with. Use it freely — modify it, break it, rebuild it. That's how you learn.

When you're done testing, delete it. Not rename. Not move. Delete.

In a real logbook, nobody needs dummy data mixed in with actual entries. It will confuse the reports, corrupt the calorie totals, and produce exports you wouldn't want to send to anyone. The file is always available here if you need it again. Your tracker should start clean.

Good job.

Seven rounds. A working calorie tracker — input validation, three reports, persistence, file export. Built step by step, decision by decision.

The next article closes the loop on what this code can become — and where the same logic applies elsewhere.

[ login to bookmark ] // copied! 30 views · 3 min
// resources
Other food_log.txt Exercise calories_tracker.py
← prev Calories Tracker Project — Round 6/7 next → Calories Tracker Project — What This Code Can Become
// 0 comments
// No comments yet. Be the first.
// leave a comment

// Your comment will appear after approval.