0コメント

もうデータが消えない!PythonとJSONで作る「覚える」To-Doリスト入門



【実務の第一歩】Pythonでデータを「記憶」させる!JSONでTo-Doリストを永続化


Python初心者がぶつかる壁の一つが「データが消える問題」です。このステップでは、**JSON**と**ファイルI/O**の技術を組み合わせ、プログラム終了後もタスクを保持する「永続化」の仕組みを実装します。実務で必須のスキルをこのコードで習得しましょう!



セクション 1: To-Doリストの完成形コード(コピペOK)


まずは以下の完成コード全体をコピーし、todo_app_final.pyとして保存して実行してみてください。データの保存・読み込みが自動で行われることを確認しましょう。




import json

import sys # 終了時のエラー処理に備えてimport


FILE_NAME = "todo_data.json"

todo_list = []


def display_menu():

    """メニューを表示する関数"""

    print("\n--- ToDoリストメニュー ---")

    print("1: タスクを追加")

    print("2: タスクを表示")

    print("3: タスクを削除")

    print("4: 終了")


def add_task():

    """タスクを追加する関数"""

    task = input("追加するタスクを入力してください: ")

    todo_list.append(task)

    print(f"'{task}' をリストに追加しました。")


def show_tasks():

    """タスクを一覧表示する関数"""

    if not todo_list:

        print("To-Doリストにタスクはありません。")

        return


    print("\n--- 現在のタスク ---")

    for index, task in enumerate(todo_list):

        print(f"{index + 1}. {task}")


def delete_task():

    """タスクを削除する関数"""

    show_tasks()

    if not todo_list:

        return


    try:

        task_number = int(input("削除したいタスクの番号を入力してください: "))

        task_index = task_number - 1


        if 0 <= task_index < len(todo_list):

            deleted_task = todo_list.pop(task_index)

            print(f"'{deleted_task}' を削除しました。")

        else:

            print("無効な番号が入力されました。")

    except ValueError:

        print("入力が不正です。番号を入力してください。")

    except Exception as e:

        print(f"予期せぬエラーが発生しました: {e}")



# --- データ永続化のためのファイル操作関数 ---


def save_tasks():

    """タスクをJSONファイルに保存する関数"""

    try:

        # 'w':書き込みモード、'utf-8':日本語対応

        with open(FILE_NAME, 'w', encoding='utf-8') as f:

            json.dump(todo_list, f, ensure_ascii=False, indent=4)

        print("[💾 保存完了] タスクをファイルに保存しました。")

    except Exception as e:

        print(f"[🚨 エラー] 保存中にエラーが発生しました: {e}")


def load_tasks():

    """タスクをJSONファイルから読み込む関数"""

    global todo_list

    try:

        # 'r':読み込みモード

        with open(FILE_NAME, 'r', encoding='utf-8') as f:

            todo_list = json.load(f)

        print("[📂 読込完了] 前回のタスクを読み込みました。")

    except FileNotFoundError:

        print("[💡 初回起動] 保存ファイルが見つかりませんでした。新しいリストで開始します。")

    except json.JSONDecodeError:

        print("[⚠️ データ破損] 保存ファイルの内容が不正です。新しいリストで開始します。")

    except Exception as e:

        print(f"[🚨 エラー] 読み込み中に予期せぬエラーが発生しました: {e}")



# --- アプリケーションのメイン処理 ---


def main():

    """アプリケーションのメインループ"""

    load_tasks() # ★起動時に必ず読み込み★


    while True:

        display_menu()

        choice = input("選択してください(1-4): ")


        if choice == '1':

            add_task()

        elif choice == '2':

            show_tasks()

        elif choice == '3':

            delete_task()

        elif choice == '4':

            save_tasks() # ★終了前に必ず保存★

            print("ToDoリスト管理ツールを終了します。ありがとうございました!")

            sys.exit() # プログラムを安全に終了

        else:

            print("無効な選択です。1から4の番号を入力してください。")


if __name__ == "__main__":

    main()



セクション 2: 核心技術の解説と学習ポイント



2-1. データ永続化の鍵:ファイルI/OとJSON



学べること: データ永続化JSON形式with open()構文


プログラムが持つメモリ上のデータ(todo_list)を、ハードディスク上のファイルに書き込み、終了後も残すのが永続化です。JSON(JavaScript Object Notation)は、Pythonのリストや辞書と非常に相性が良く、データをテキストファイルに変換する標準的な方法です。



    • 'w' (Write): ファイルを**上書き**して保存します。

    • 'r' (Read): ファイルを**読み込み**ます。

    • json.dump(): Pythonデータ → JSON形式(ファイルへ書き込み)

    • json.load(): JSON形式(ファイルから読み込み)→ Pythonデータ




2-2. 堅牢なアプリの必須技術:エラーハンドリング



学べること: try...except構文例外処理


ファイル操作は失敗しやすい処理です。例えば、保存ファイルが削除されていたり、中身が壊れていたりする場合などです。アプリがクラッシュしないよう、あらかじめエラーが起きた場合の「逃げ道」を作っておくのが**エラーハンドリング(例外処理)**です。



    • try: エラーが発生する可能性のあるコードを記述します。

    • except FileNotFoundError: ファイルが見つからないという特定の例外を捕まえ、アプリが優しいメッセージを出して継続できるようにしています。

    • except json.JSONDecodeError: ファイルの内容がJSONとして読めない(データが壊れている)場合に処理します。




2-3. アプリの実行を制御するメイン処理



学べること: グローバル変数while Trueループ関数の実行順序


def main():

    load_tasks()  # ① 最初に実行されることでデータを復元

    while True: # ② アプリを終了させるまで無限に繰り返す

        # ... 処理 ...

        elif choice == '4':

            save_tasks() # ③ 終了直前にデータを保存

            break # ④ ループを終了し、アプリを閉じる


    • global todo_list: load_tasks関数内で使用。関数外で定義されたリストの中身を関数内で変更するために必要です。

    • 実行の肝は、load_tasks()を**無限ループの前**に、save_tasks()を**無限ループの終了時**に呼び出す点です。






この記事へのコメント