3日目のゴール
3日目のテーマは
「try / except を“入力だけ”で終わらせず、アプリ全体の安全装置として使う」 ことです。
1日目:単発の入力を try / except で守れるようになった。
2日目:安全な入力関数として再利用できる形にした。
3日目では一歩進んで、
ファイル読み書きに try / except を使う
メニュー選択のミスを落ちないようにする
「どこで try を使うか」を意識して設計する
という、“アプリ全体を守る視点” を身につけます。
「入力以外でもエラーは起きる」という感覚を持つ
典型的に落ちる場所を整理する
ここまでの2日間で、
「ユーザー入力 → 型変換」のところにValueError が起きることは体感できたと思います。
でも、アプリが落ちる場所はそこだけではありません。
ファイルを開くとき(存在しない、権限がない)
JSONを読み込むとき(壊れている)
0で割るとき
存在しないキーやインデックスにアクセスするとき
つまり、「外部と関わる場所」や「境界」 で
エラーはよく起きます。
3日目は、その中でも特に大事な
「ファイル」と「メニュー入力」を題材にします。
ファイル読み込みに try / except を使う
まずは「危険な」ファイル読み込み
次のようなコードを考えます。
filename = "data.txt"
with open(filename, "r", encoding="utf-8") as f:
text = f.read()
print("ファイルの中身:")
print(text)
Pythonこのコードは、data.txt が存在していれば問題なく動きます。
でも、ファイルがなかったり、
権限がなかったりすると、こうなります。
FileNotFoundError: [Errno 2] No such file or directory: 'data.txt'
Pythonプログラムはそこで終了です。
try / except で「落ちない読み込み」にする
ここに try / except を入れてみます。
filename = "data.txt"
try:
with open(filename, "r", encoding="utf-8") as f:
text = f.read()
except FileNotFoundError:
print(f"{filename} が見つかりませんでした。")
text = ""
except PermissionError:
print(f"{filename} を読む権限がありません。")
text = ""
else:
print("ファイルを正常に読み込みました。")
print("ファイルの中身:")
print(text)
Pythonここでの重要ポイントを深掘りします。
一つ目は、
「どの例外を捕まえるかを具体的に書いている」 ことです。FileNotFoundError と PermissionError を分けることで、
ユーザーに伝えるメッセージも変えられます。
二つ目は、except の中で text = "" としていることです。
これにより、「読み込みに失敗したけど、空として扱う」という
“アプリとしての方針” を決めています。
三つ目は、else を使って
「エラーがなかったときだけメッセージを出す」
という書き分けをしていることです。try の中が成功したかどうかが、視覚的に分かりやすくなります。
ファイル読み込みを関数にして「安全な入り口」にする
アプリの外とつながるところを1か所に集約する
ファイル読み込みは、
アプリと外の世界(ファイルシステム)との境界です。
ここに try / except を集中させると、
アプリ全体がぐっと安定します。
def load_text_file(filename):
try:
with open(filename, "r", encoding="utf-8") as f:
text = f.read()
except FileNotFoundError:
print(f"{filename} が見つかりませんでした。空のデータとして扱います。")
return ""
except PermissionError:
print(f"{filename} を読む権限がありません。空のデータとして扱います。")
return ""
else:
return text
Python使う側は、こう書くだけです。
text = load_text_file("data.txt")
print("読み込んだ内容:")
print(text)
Pythonここでの本質は、
「ファイル読み込みの try / except を、アプリのあちこちに書かない」
「外部との境界に“安全な入り口”を1つ作る」
という設計の考え方です。
メニュー入力にもエラーハンドリングを入れる
ありがちな「メニューで落ちる」パターン
よくあるメニューコードは、こんな感じです。
print("1: 足し算")
print("2: 引き算")
print("0: 終了")
choice = int(input("番号を選んでください: "))
if choice == 1:
print("足し算をします。")
elif choice == 2:
print("引き算をします。")
elif choice == 0:
print("終了します。")
else:
print("不正な番号です。")
Pythonここで「a」などを入力すると、int("a") で ValueError が出て、アプリが落ちます。
メニュー入力を「安全な整数入力」で守る
2日目で作った「安全な整数入力関数」を
メニューにも使ってみます。
def input_menu_number(prompt):
while True:
text = input(prompt)
try:
value = int(text)
except ValueError:
print("数字で入力してください。\n")
continue
return value
Pythonこれを使ってメニューを書くと、こうなります。
def main():
while True:
print("1: 足し算")
print("2: 引き算")
print("0: 終了")
choice = input_menu_number("番号を選んでください: ")
if choice == 1:
print("足し算をします。\n")
elif choice == 2:
print("引き算をします。\n")
elif choice == 0:
print("終了します。")
break
else:
print("その番号のメニューはありません。\n")
main()
Pythonここでのポイントは、
「数字以外で落ちる」問題は try / except で防ぎ、
「範囲外の数字」は if / else で扱っている
という分け方です。
try / except はあくまで
「型変換に失敗したとき」のためのもの。
「値として妥当かどうか」は、
通常の条件分岐でチェックする方が読みやすくなります。
「どこまで try に入れるか」を意識する
なんでもかんでも try に入れると、逆に読みにくい
悪い例をあえて出します。
try:
choice = int(input("番号を選んでください: "))
if choice == 1:
print("足し算をします。")
elif choice == 2:
print("引き算をします。")
elif choice == 0:
print("終了します。")
else:
print("その番号のメニューはありません。")
except ValueError:
print("数字で入力してください。")
Python一見スッキリしているように見えますが、try の中に「本来エラーと関係ない処理」まで入っています。
3日目で身につけてほしい感覚は、
「try の中には“本当にエラーが起きうる行”だけを入れる」
ということです。
例えば、こう分けるとスッキリします。
text = input("番号を選んでください: ")
try:
choice = int(text)
except ValueError:
print("数字で入力してください。")
else:
if choice == 1:
print("足し算をします。")
elif choice == 2:
print("引き算をします。")
elif choice == 0:
print("終了します。")
else:
print("その番号のメニューはありません。")
Pythontry の中は「intに変換する1行だけ」。
その後のロジックは else の中に分離されています。
3日目のミニアプリ:メモをファイルに保存する簡易アプリ+エラーハンドリング
仕様を決める
シンプルな「テキストメモアプリ」を作ります。
メニューで「1: メモを書く」「2: メモを読む」「0: 終了」
メモは memo.txt に保存する
ファイルがなくても落ちない
メニュー入力のミスでも落ちない
ここに、今日の try / except を組み込みます。
安全なファイル読み書き関数を書く
import os
FILENAME = "memo.txt"
def load_memo():
if not os.path.exists(FILENAME):
print("メモファイルがまだありません。空のメモとして扱います。")
return ""
try:
with open(FILENAME, "r", encoding="utf-8") as f:
text = f.read()
except OSError:
print("メモファイルを読み込めませんでした。")
return ""
return text
def save_memo(text):
try:
with open(FILENAME, "w", encoding="utf-8") as f:
f.write(text)
except OSError:
print("メモファイルに書き込めませんでした。")
else:
print("メモを保存しました。")
Pythonここでの重要ポイントは、
FileNotFoundError を os.path.exists で事前に避けている
それでも起きうるファイル関連のエラーを OSError でまとめて捕まえている
という二段構えです。
メニュー+入力エラーハンドリングを組み合わせる
def input_menu_number(prompt):
while True:
text = input(prompt)
try:
value = int(text)
except ValueError:
print("数字で入力してください。\n")
continue
return value
def main():
while True:
print("\n=== メモアプリ ===")
print("1: メモを書く")
print("2: メモを読む")
print("0: 終了")
choice = input_menu_number("番号を選んでください: ")
if choice == 1:
print("\n=== メモを書く ===")
print("今のメモ内容は次の通りです。")
current = load_memo()
print("----- 現在のメモ -----")
print(current)
print("----------------------")
print("新しいメモ内容を入力してください。(上書きされます)")
new_text = input("> ")
save_memo(new_text)
elif choice == 2:
print("\n=== メモを読む ===")
text = load_memo()
print("----- メモ内容 -----")
print(text)
print("--------------------")
elif choice == 0:
print("終了します。")
break
else:
print("その番号のメニューはありません。\n")
main()
Pythonこの時点で、
ファイルがなくても落ちない
ファイルが読めなくても落ちない
メニューに変な文字を入れても落ちない
という、「落ちないアプリ」になっています。
3日目で絶対に押さえてほしい本質
try / except は「境界を守るガードマン」
今日いちばん伝えたいのは、
try / except は
ユーザー入力だけのためのものではなく、
「アプリと外の世界の境界」を守るための仕組み
だということです。
入力 → 型変換
ファイル → 読み書き
JSON → パース
こういった「外から来たもの」を扱う場所にtry / except を置いてあげると、
アプリは一気に“壊れにくく”なります。
そしてもう一つ大事なのは、
どこまでを try に入れるかを意識する
本当にエラーが起きうる行だけを囲う
それ以外のロジックは、通常の if / else に任せる
という「線引きのセンス」です。
4日目以降は、このエラーハンドリングを
JSON保存アプリや、より複雑な入力フローに組み込んでいきます。
今日のミニアプリを、自分なりに機能追加しながら
「どこに try を置くと気持ちいいか」を探ってみてください。


