Pythonでの「例外処理」の基本と実践的な使い方:プログラムの停止を防ぐための知恵
![]()
【Yuki】
Hiroki君、こんにちは。今日はPythonの学習の中でも、特に大切で、かつプログラムを「丈夫」にするために欠かせない例外処理についてお話ししようと思います。
![]()
【Hiroki】
こんにちは、Yukiさん!例外処理、ですか……。なんだか難しそうな響きですね。以前、コードを書いていてエラーが出たときにプログラムが止まってしまって、どうすればいいか分からなくなったことがあるんですけど、それに関係することでしょうか?
![]()
【Yuki】
ええ、まさにその通りです。プログラムを動かしていると、どうしても避けられない「予期せぬ事態」が起こることがあります。例えば、ユーザーが数字を入力すべきところに文字を入れてしまったり、開こうとしたファイルが存在しなかったり……。そういったときに、プログラムをただ強制終了させるのではなく、「どう対処するか」をあらかじめ決めておくことが例外処理の役割なんです。
![]()
【Hiroki】
なるほど。エラーが起きたときにパニックにならずに、優しくエスコートしてあげるようなイメージですね。
![]()
【Yuki】
ふふ、そうですね。その表現、素敵だと思います。プログラムを「守ってあげる」ための知識を、これからゆっくり紐解いていきましょう。
例外とは何か?
![]()
【Yuki】
まず、プログラミングにおける「例外(Exception)」とは何かを確認しておきましょう。多くの初心者は、文法の間違いである「構文エラー(SyntaxError)」と混同してしまいがちですが、これらは別物なんです。
![]()
【Hiroki】
構文エラーは、実行する前にPythonが「書き方が間違っているよ」と教えてくれるものですよね。
![]()
【Yuki】
その通りです。対して「例外」は、文法としては正しいけれど、実行中に発生するエラーのことを指します。例えば、10を0で割ろうとしたときに出る ZeroDivisionError や、存在しない変数を使おうとしたときの NameError などがあります。
![]()
【Hiroki】
動かしてみて初めて気づくエラー、ということですね。
![]()
【Yuki】
はい。これらが解決されないまま発生すると、Pythonは処理を中断して「トレースバック」というエラーメッセージを出して止まってしまいます。これを防ぐために、あらかじめ「もしこういうエラーが起きたら、こう動いてね」と予約しておくのが例外処理の基本です。
try...exceptの基本構造
![]()
【Yuki】
では、実際にどう書くのかを見てみましょう。一番基本となるのが try と except を使った書き方です。
try:
# エラーが発生する可能性のある処理
number = int(input("数字を入力してください: "))
result = 10 / number
print(f"計算結果は {result} です")
except ValueError:
# ValueErrorが発生したときの処理
print("エラー:数字以外が入力されました。")
except ZeroDivisionError:
# ZeroDivisionErrorが発生したときの処理
print("エラー:0で割ることはできません。")
![]()
【Hiroki】
わあ、意外とシンプルですね。try の中に「試してみたい処理」を書いて、except の後ろに「防ぎたいエラーの名前」を書く、という形でしょうか。
![]()
【Yuki】
その通りです、Hiroki君。飲み込みが早いですね……。
try ブロックの中でエラーが起きた瞬間、それ以降の処理はスキップされて、対応する except ブロックにジャンプします。もし何のエラーも起きなければ、except ブロックは無視されて次の処理に進みます。
![]()
【Hiroki】
これなら、入力ミスがあってもプログラムがいきなり終了することはないんですね。でも、エラーの名前を全部覚えるのは大変そうです……。
![]()
【Yuki】
そうですね。確かにPythonにはたくさんの例外クラスがありますが、よく使うものは限られています。また、特定の例外を指定せずにキャッチする方法もありますが、それは少し注意が必要かもしれません。
複数のエラーをまとめて扱う、あるいは詳細を取得する
![]()
【Hiroki】
特定の例外を指定しない方法、というのはどういうことですか?
![]()
【Yuki】
例えば、このように書くことができます。
try:
# 何らかの処理
pass
except Exception as e:
# すべての例外をキャッチする
print(f"予期せぬエラーが発生しました: {e}")
![]()
【Yuki】
Exception というのは、ほとんどの例外の親玉のようなものです。これを使うと、どんなエラーが起きても捕まえることができます。また、as e と書くことで、エラーの内容(メッセージ)を e という変数に取り出すことができるんです。
![]()
【Hiroki】
「何が起きたか」を詳しく知りたいときに便利そうですね。でも、さっき「注意が必要」とおっしゃっていたのはなぜですか?
![]()
【Yuki】
それは……何でもかんでもキャッチしてしまうと、本来修正すべきバグまで見逃してしまう可能性があるから、だと思います。例えば、変数名の打ち間違いという単純なミスまで「予期せぬエラー」として処理されてしまうと、どこが間違っているのか探しにくくなってしまいますよね。
![]()
【Hiroki】
あ、確かに。本来はプログラムを直すべきなのに、エラーを隠してしまうことになるんですね。
![]()
【Yuki】
はい。ですので、基本的には「発生することが予想されるエラー」を個別に指定するのが、良い書き方だとされています。どうしても広い範囲で捕まえたいときだけ、Exception を使うようにするのが無難かもしれませんね。
elseとfinallyの役割
![]()
【Yuki】
例外処理には、try と except 以外にも、else と finally という便利なキーワードがあります。これらを使うと、処理の流れをより細かく制御できるんですよ。
![]()
【Hiroki】
else って、if 文以外でも使えるんですか?
![]()
【Yuki】
そうなんです。例外処理における else は、「エラーが一つも発生しなかったときにだけ実行される処理」を書くために使います。
try:
f = open("data.txt", "r")
except FileNotFoundError:
print("ファイルが見つかりませんでした。")
else:
print("ファイルを正常に読み込みました。")
content = f.read()
print(content)
f.close()
![]()
【Hiroki】
なるほど。成功したとき専用のルート、という感じですね。じゃあ、finally はどういう役割なんですか?
![]()
【Yuki】
finally はもっと健気な子なんです。「エラーが起きても起きなくても、最後に必ず実行される処理」を書きます。
![]()
【Hiroki】
必ず実行される……。それって、どんな時に使うんでしょうか。
![]()
【Yuki】
一番多いのは、「後片付け」ですね。例えば、ファイルを開いたり、データベースに接続したりしたとき、エラーが起きて途中で止まってしまっても、最後に必ず「ファイルを閉じる」という処理をしないと、コンピュータのメモリを無駄に使ってしまうことがあります。
try:
f = open("important_data.txt", "r")
# 何か複雑な処理
except Exception as e:
print(f"エラーが発生しました: {e}")
finally:
# 成功しても失敗しても、ファイルが開かれていれば必ず閉じる
if 'f' in locals():
f.close()
print("ファイルを安全に閉じました。")
![]()
【Hiroki】
どんな状況でも最後にはきれいに片付ける、お掃除担当みたいなイメージですね。
![]()
【Yuki】
ええ。特にネットワーク通信やデータベースの操作など、外部の資源を扱うときは、この finally がとても大切になります。プログラムを安全に終わらせるための、最後の手立てだと考えてください。
自ら例外を発生させる:raise
![]()
【Hiroki】
ここまでは「起きてしまったエラーに対処する」方法でしたが、逆に自分でエラーを起こすこともあるんですか?
![]()
【Yuki】
はい、よく気づきましたね。実は、特定の条件のときにわざと例外を発生させる raise というキーワードがあります。
![]()
【Hiroki】
わざとエラーを出すなんて、なんだか意地悪な気がしてしまいますが……。
![]()
【Yuki】
ふふ、そう感じるかもしれませんね。でも、これはプログラムの「ルールを守らせる」ために必要なことなんです。例えば、年齢を入力する欄にマイナスの数字が入ってきたら、プログラムとしては計算できても、論理的にはおかしいですよね。
![]()
【Hiroki】
確かに、マイナス10歳なんて人は存在しませんもんね。
![]()
【Yuki】
そういうときに、「それは不正な値ですよ!」とエラーを投げてあげるんです。
def check_age(age):
if age < 0:
raise ValueError("年齢にマイナスの値は指定できません。")
return f"年齢は{age}歳ですね。"
try:
print(check_age(-5))
except ValueError as e:
print(f"入力エラー: {e}")
![]()
【Hiroki】
なるほど!あえて例外を出すことで、その後の処理で大きな問題になる前に、間違いを指摘してあげられるんですね。
![]()
【Yuki】
その通りです。これによって、関数を使う側に対して「正しい使い方をしてください」と伝えることができるんです。丁寧なプログラミングには欠かせない技術かもしれません。
実践的な例外処理の考え方
![]()
【Hiroki】
Yukiさん、例外処理の使い方は分かりました。でも、どこまで細かく書けばいいのか迷ってしまいそうです。全部の行を try で囲むわけにもいきませんよね?
![]()
【Yuki】
そうですね……。実は、例外処理には大きく分けて二つの考え方があります。「石橋を叩いて渡る」方法と、「失敗してから謝る」方法です。
![]()
【Hiroki】
「失敗してから謝る」?
![]()
【Yuki】
はい。Pythonの文化では EAFP (Easier to Ask for Forgiveness than Permission) と呼ばれる考え方が好まれることが多いんです。「事前に細かくチェックするより、まずはやってみて、失敗したら対処するほうがコードがすっきりする」という考え方です。
![]()
【Hiroki】
へぇー!事前に if 文でたくさんチェックするより、とりあえず try してみるほうがPythonらしい、ということなんですね。
![]()
【Yuki】
ええ。もちろん時と場合によりますが、例外処理をうまく使うと、メインとなる処理(ハッピーパスと言ったりします)がシンプルに見えるようになるんです。
![]()
【Hiroki】
ハッピーパス……。順調にいったときの道のり、ということですね。なんだかいい言葉です。
![]()
【Yuki】
例外処理を学ぶと、最初は「エラーが出るのが怖い」と思っていたのが、次第に「エラーをコントロールできている」という感覚に変わっていくと思います。そうなれば、Hiroki君の書くコードは、もっと強くて優しいものになりますよ。
![]()
【Hiroki】
ありがとうございます!僕も、エラーが起きても慌てずに、しっかりと後片付けまでできるようなプログラムを書いてみたいと思います。
![]()
【Yuki】
その意気です。最初は難しく感じるかもしれませんが、少しずつ慣れていけば大丈夫ですよ。もし困ったことがあったら、いつでも聞いてくださいね。……わたしも、たまにコードの書き間違いをして、自分の出したエラーメッセージにびっくりしちゃうことがあるので、一緒に頑張りましょう。
![]()
【Hiroki】
Yukiさんでもそんなことがあるんですね。ちょっと安心しました(笑)。
![]()
【Yuki】
……あ、今の話は秘密にしておいてくださいね? 講師として、少し恥ずかしいですから。
参考文献・公式ドキュメント - Python チュートリアル - 8. エラーと例外 - Python 標準ライブラリ - 組み込み例外
この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。
「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。
- 専門家の知見に基づいた、保守性の高いコード設計
- AIの専門家による、Gemini API等の最新AIを組み合わせた高度な自動化
- ChatGPT等が生成したコードのデバッグ・最適化
「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。


