Article by: Abdul D
本ブログの内容
- Python におけるエラーと例外 − その違いとは
- Python におけるエラー
- Pythonにおける例外
- なぜ Python において例外・エラー処理が重要なのか
- Sentry は Python アプリのエラー監視にどのように役立つのか
Python のコードで、原因か分からないエラーメッセージに遭遇したことはありませんか?
それはあなただけではありません。経験豊富な開発者でさえ例外に直面するため、効果的に対処する方法を理解することが重要です。
基本的な構文エラーはコードエディタやデバッグツールによって早期に検出できますが、より複雑な問題は実行時に発生することが多く、体系的な例外処理のアプローチが求められます。
経験の有無にかかわらず、すべての Python 開発者が例外処理を習得することで恩恵を受けられます。本ガイドでは、エラーと例外の違いを理解し、一般的な例外の種類を確認したうえで、Python アプリケーションにおける適切な対処方法を学びます。
また、Sentry を使ってリアルタイムで例外を監視・追跡する方法についても解説し、アプリケーションのパフォーマンスと安定性に関する詳細なインサイトを得る手段を紹介します。
Sentry トレーシング
Python におけるエラーと例外 − その違いとは
完璧なコードを書くことは非現実的な期待であり、すべての開発者はコーディングミスによる予期しない動作に直面するものです。これらの問題は一般的にエラーと例外の2つに分類されます。
エラーはプログラムの実行を完全に妨げる根本的なコーディングミスです。エラーは通常コンパイル時に検出され、修正されるまでコードは実行されません。
例外はエラーの一種であり、プログラムの実行中(ランタイム)に予期しない状況、例えばゼロ除算のような場合に発生します。
result = 10 / 0 # Raises ZeroDivisionError
エラーとは異なり、例外はコード内で捕捉して処理することができます。
エラー処理 vs デバッグ
エラー処理とデバッグは密接に関連していますが、開発プロセスにおいて異なる目的を果たします。
エラー処理は能動的な対応であり、コード内の潜在的な問題を予測してクラッシュを防止し、ユーザーに意味のあるフィードバックを提供する仕組みを実装することです。
デバッグは受動的な対応であり、問題が発生した後にその原因を特定して解決する作業です。ブレークポイント、ログ出力、スタックトレースなどのデバッグツールを使用することで、問題の原因を把握し、修正方法を見出すことができます。
Python におけるエラー
構文エラーのようなエラーは、Python インタープリタが実行前の構文解析時に問題を検出した際に発生し、プログラムの実行を完全に妨げます。これらのエラーはコード構造における根本的な問題を反映しているため、実行を続ける前に修正する必要があります。
Python における一般的なエラー
構文エラーやインデントエラーは、Python で最も一般的なエラー一部であり、コードがバイトコードに変換されるのを妨げます。
SyntaxError は、コードが Python の構文ルールに従っていないために、Python がコードを構文解析できない場合に発生します。例えば、次のように閉じ括弧が欠けているコードを含むスクリプトを実行しようとすると…
Python インタープリタは次のエラーメッセージを返します。
File “example.py”, line 2
SyntaxError: unexpected EOF while parsing
IndentationError は、Python がインデントされたコードブロックを期待しているにもかかわらず、インデントが不足していたり誤っていた場合に発生します。
以下のコードでは、インデントが正しくないために IndentationError: expected an indented block が発生します。
構文エラーやインデントエラーは、新しいコードを記述したり、既存のコードを変更したときによく発生します。これらは厄介に感じることもありますが、エラーメッセージの意味を理解すれば簡単に修正できます。
Pythonにおける例外
例外はプログラムの実行中に発生し、コードの通常の流れを妨げるエラーの一種です。例外が発生すると、Python は実行を停止し、何が問題だったかを含む例外オブジェクトを生成します。その後インタープリタは、例外を処理するための適切な except ブロックを探します。見つからない場合、Python は実行を終了し、デバッグのためのトレースバックメッセージを表示します。
Python における一般的な例外の種類
Python には、さまざまなエラーシナリオを処理するための組み込みの例外クラスが用意されています。ここでは、よく遭遇する代表的な例外を紹介します。
型や値に関連する例外
- TypeError:互換性のない型に対して演算を行おうとしたときに発生します(例:文字列と整数を加算しようとした場合など)。
- ValueError:関数が実行に適さない値を引数として受け取ったときに発生します(例:数値でない文字列を整数に変換しようとした場合など)。
データ構造に関連する例外
- KeyError:存在しない辞書のキーにアクセスしようとしたときに発生します。
- IndexError:リストや配列の範囲外のインデックスにアクセスしようとしたときに発生します。
数学関連の例外
- ZeroDivisionError:ゼロによる除算を試みたときに発生します。
- OverflowError:結果の値が許容される数値の範囲を超えたときに発生します。
ファイル操作に関連する例外
- FileNotFoundError:存在しないファイルにアクセスしようとしたときに発生します。
独自の例外クラスの作成
Python の Exception クラスを拡張して、アプリケーション固有のケースを処理するための独自の例外クラスを定義することができます。
Python で例外の詳細を取得して表示する方法
Python コードで例外が発生したとき、何が問題だったのかを理解することが問題解決の鍵です。例外の詳細には、エラーの種類、発生箇所、および原因に関する情報が含まれています。
Python が実行時に例外に遭遇すると、以下の情報を含む例外オブジェクトを生成します。
- 例外の種類(例:ZeroDivisionError)
- エラーの内容(例:ゼロによる除算)
- Traceback(エラーが発生した正確な場所を示します)
except _____ as を使って例外情報を捕捉することで、例外オブジェクトから情報を抽出し、エラーメッセージとして出力することができます。以下はその例です。
このコードは次のような見やすいエラーメッセージを出力します。
traceback を使用して詳細なエラー情報を取得する
Python の traceback モジュールは、例外やエラーに関する詳細な情報(コールスタックを含む)を抽出・整形・出力するための標準インターフェースを提供します。これにより、何が問題だったのかを深く理解でき、特に複雑な問題のデバッグやエラーの背景を把握する際に役立ちます。特に、コールスタックを見ることで、問題の根本原因を特定することが可能になります。
以下は例外発生時に traceback を使ってログを出力する例です。
Pythonでの例外処理方法
Python の例外ハンドラを使うことで、問題が発生してもプログラムを強制終了させず、代替の処理経路を提供することができます。例外ハンドラは、ユーザー入力やファイル操作、ネットワークリクエストなどで予期しないエラーが発生した場合に特に有効で、プログラムの継続実行を可能にします。
try と except ブロックの使用
try ブロックは例外が発生する可能性のあるコードを実行し、except ブロックは発生した例外を捕捉して処理します。この構造により、例外が発生してもプログラムを継続して動かせるだけでなく、例外の詳細を確認することも可能です。
else と finally ブロックの使用
try ブロックは else や finally ブロックと組み合わせて、追加の機能を提供することができます。else ブロックは例外が発生しなかった場合にのみ実行され、finally ブロックは例外の有無にかかわらず常に実行されます。
次のコード例では、try ブロックでファイルを開きます。例外が発生しなければ、else ブロックでファイル内容を読み取り、ファイルを閉じます。
複数の例外を捕捉する
except ブロックを連続して記述するか、1つの except ブロック内でタプルを使うことで、複数の種類の例外を捕捉することができます。
例えば、ValueError と ZeroDivisionError の両方に対応するには、次のように記述します。
デバッグのために例外をログに記録する
コンソールに表示されたエラーは、プログラム終了とともに消えてしまいます。後から実行内容を分析したい場合は、logging モジュールを使ってエラーをファイルに記録することができます。
このコードでは、エラーが errors.log ファイルに記録され、何が問題だったのか後から確認できます。Python の logging モジュールは非常に強力で、さまざまなレベルのエラーを記録したり、複数の出力先に送るよう設定することも可能です。詳しくは Python Logging Guide を参照してください。
独自の例外クラスを活用する
Python の Exception クラスを継承して、アプリケーション固有のケースを処理するための独自の例外クラスを定義することができます。こうした独自例外を使うことで、用途に応じたエラー処理が可能になり、エラーメッセージの明確化やデバッグの簡素化にもつながります。
コードのリントを行う
Pylint や flake8 のようなツールを使用すると、実行前に構文やインデントの問題を検出できます。これらのツールはコードに対するスペルチェックのように機能し、実行時のエラーになる前に問題を早期に発見できます。
なぜ Python において例外・エラー処理が重要なのか
効果的なエラーや例外処理は、アプリケーションが堅牢か、頻繁にクラッシュするかを左右します。以下に、適切なエラー処理が必要な理由を示します。
1. 予期しないプログラムのクラッシュを防ぐ
未処理の例外が発生すると、Python は即座にプログラムを終了します。例外を適切に処理すれば、プログラムのクラッシュを回避し、正常な復旧処理を提供できます。
この例では、ユーザーに数値の入力を求めています。0を入力すると、ZeroDivisionError をキャッチしてクラッシュを防ぎ、ユーザーにわかりやすいメッセージを表示します。非数値を入力した場合も、ValueError をキャッチして再入力を促します。
いずれの場合も、入力値が有効になるまでプログラムはクラッシュせず継続し、条件を満たすとループを抜けます。
Python の例外処理
例外を適切に処理することで、プログラムの安定性が保たれ、問題の原因を把握し修正するための有用な情報を得ることができます。
2. ユーザーに対して意味のあるフィードバックを提供する
有益なエラーメッセージを表示することで、ユーザーは何が問題だったのか、どのように入力や操作を修正すべきかを理解できます。たとえば、存在しないファイルを開こうとしたときに FileNotFoundError をキャッチして、ファイルが存在しないことを知らせるメッセージを表示できます。
難解なトレースバックの代わりに、ユーザーには明確なファイルの欠如に関するメッセージが表示されます。
3. デバッグを簡略化し、詳細なログ記録を可能にする
例外処理を行うことで、後から分析できるようにエラーをログに記録することができ、問題の発生源を特定しやすくなります。特に本番環境では、コードを対話的にデバッグできないため、ログ記録は非常に役立ちます。Python でのロギングに関する詳細は Python Logging Guide を参照してください。
4. リソースの適切な解放を保証する
例外を適切に処理することで、開いたファイル、データベース接続、ネットワークソケットなどのリソースを適切に閉じることができ、メモリリークやデータ破損を防げます。Python ではメモリ管理は自動ですが、リソースの解放は自動ではないため、明示的に閉じる必要があります。with ブロックやコンテキストマネージャを使用することで、確実にリソースを解放できます。
5. セキュリティ上の脆弱性を減らす
たとえば、プロジェクトで環境変数に保存された API キーを使用している場合、API コールが失敗した際にそのキーがログに出力されるのを避けたいでしょう。
次の例をご覧ください。
# 以下の環境変数が設定されていると仮定します
# export SECRET_API_KEY=this-is-a-secret
HTTP リクエストが失敗した場合、ログには次のようなエラーが表示される可能性があります。
ご覧のとおり、ログに this-is-a-secret というキーが表示されており、これは避けるべき事態です。
例外を適切に処理することで、こうした問題を回避できます。以下はそのシンプルな例です。
このようにすると、リクエストが失敗した場合の出力は以下のようになります。
Connection error when accessing api.example.com
情報量は少なくなりますが、そのぶん安全性は高くなります。実際の運用では、デバッグのしやすさと機密情報漏えい防止のバランスを考慮して、ログに何を残すか慎重に判断する必要があります。
Sentry は Python アプリのエラー監視にどのように役立つのか
本番環境では、特にエラーや問題が発生した際に、アプリケーションのパフォーマンスを正確に把握するのは困難です。可視性が確保されていないと、問題の特定や修正に時間がかかり、ダウンタイムの増加、ユーザー満足度の低下、改善機会の損失などにつながる恐れがあります。
Sentry は Python アプリケーションのモニタリングを強化することで、こうした課題を解決します。本番環境における例外、エラー、パフォーマンス問題をリアルタイムで包括的に可視化し、単なるあいまいなエラーメッセージやログではなく、スタックトレースを含む詳細なコンテキスト情報や、エラー発生時の具体的な条件まで記録します。この豊富なデータセットにより、開発者は「何が起きたか」だけでなく、「なぜ起きたか」という状況も把握しやすくなり、問題の再現、特定、修正を迅速に行えるようになります。
Sentry の使い始め方
Sentry を使って例外をキャプチャする方法をシミュレーションしてみましょう。まず、Python 用の Sentry SDK をインストールします。
pip install sentry-sdk
Sentry のアカウントとプロジェクトを作成して、DSN(Data Source Name)キーを取得する必要があります。Python での Sentry のセットアップ方法については、Sentry for Pythonドキュメントをご覧ください。
次に、Sentry がキャプチャできるように ZeroDivisionError を発生させます。
このコードを実行すると、Sentry が例外をキャプチャし、Sentry ダッシュボードで問題を確認できます。
Sentryによる例外トラッキング
問題をクリックすると、スタックトレースを含む例外の詳細情報を確認できます。
ゼロ除算エラーの詳細
トレースビューによる詳細なコンテキスト
Sentry は、各問題の発生頻度、影響を受けたユーザー、スタックトレースなどの詳細な情報を提供します。トレースビューを使えば、例外がアプリケーション内でどのように伝播したかをより深く理解できます。ブレッドクラム機能により、エラーに至るまでの詳細なイベントタイムラインを確認でき、原因の特定が容易になります。
以下の例では、トランザクションを使ってイベントに関する詳細情報を記録しています。
トランザクションとは、ページの読み込み、ナビゲーション、非同期タスクなど、測定・追跡したいアクティビティの1単位を指します。トランザクション情報は、クラッシュやエラー発生時だけでなく、アプリ全体のパフォーマンスを監視するのに役立ちます。トランザクションがないと、アプリで「何かがおかしくなった」瞬間しか把握できず、重要ではあるものの全体像が見えません。
(本番環境では、イベントクォータを使い切らないように、0.15のようなより低い値に設定することを推奨します。)
このコードを実行すると、次のような例外が発生します。
An error occurred: User already exists
そして Sentry がこの例外をキャプチャし、さらなるインサイトを提供します。
ユーザー登録時の例外トレース
トレースビューでは、スタックトレース内でエラーが「どこで」「いつ」発生したかを詳細に確認できます。
トレースビュー全体表示
トレースビューについて詳しく知りたい方や、トレースによってエラーの背景がどのように把握できるかを理解したい方は、トレースビューのドキュメントをご覧ください。
リアルタイムパフォーマンス監視
Sentry はエラーの追跡だけでなく、アプリケーションのパフォーマンスをリアルタイムで監視することも可能です。パフォーマンス指標を取得することで、エラーがアプリの動作やユーザー体験に与える影響を把握できます。
パフォーマンス指標
ユーザー中心のデバッグとダッシュボード
Sentry は、エラーや例外の集約ビューを提供し、イベント数や影響を受けたユーザー数などに基づいて問題を追跡できます。これにより、ユーザー体験への影響度に応じて優先順位をつけて対応できます。
Issues ダッシュボード
Sentry には、主要な指標やパフォーマンスデータを表示できるカスタマイズ可能なダッシュボードも用意されており、チームが傾向を把握し、課題を効果的に優先順位付けできます。
ダッシュボードチャート
Sentry はデバッグ作業を簡素化し、開発者のワークフローを改善します。安定性が高く高性能な Python アプリケーションの構築に注力するチームにとって、Sentry は極めて有用なツールです。さらに、Sentry にはユーザーに影響を与える前にコードを修正できる Python 向けのAI自動修正機能もあります。
詳細は Sentry のPython向けドキュメントをご覧いただくか、サインアップして今すぐ始めてみてください。
Original Page: Practical Tips on Handling Errors and Exceptions in Python
IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談はこちらのフォームからお気軽にお問い合わせください。