Python 3 エンジニア認定基礎試験(8章)の例外処理とエラー対策完全ガイド

Python 3 エンジニア認定基礎試験(8章)の例外処理とエラー対策完全ガイド Python
Python 3 エンジニア認定基礎試験(8章)の例外処理とエラー対策完全ガイド
※本サイトは、プロモーションが含まれます

Python 3 エンジニア認定基礎試験(8章)を攻略するためには、エラーや例外に関する深い理解が欠かせません。

本記事では、試験範囲に含まれるエラーと例外について重要なポイントをわかりやすく解説します。特に構文エラーと例外の違い、例外を処理する方法、例外を送出する際の注意点など、実務にも役立つ内容を網羅しました。

また、例外の連鎖やユーザー定義例外といった高度なトピックも取り上げ、Pythonプログラムをより堅牢にするための方法を紹介します。

加えて、クリーンアップ動作を定義する際のコツや定義済みクリーンアップ処理の便利な活用法も解説。

さらに、複数の関連しない例外の送出と処理、ノートによって例外を充実させる方法についても触れ、試験対策だけでなく実務でも即活用できる知識を提供します。

試験合格を目指し、エラー処理のスキルを確実にレベルアップさせましょう。

他にもBe Free Techではエンジニアの人が知らないと損する情報を紹介してますのでご覧ください!

  • 構文エラーと例外の違いについて理解できる
  • 例外を適切に処理する方法がわかる
  • ユーザー定義例外の作成方法を学べる
  • クリーンアップ処理や例外の連鎖について理解できる

Python 3 エンジニア認定基礎試験(8章):エラーと例外(前半)

Python 3 エンジニア認定基礎試験(8章):エラーと例外(前半)
  • 構文エラー
  • 例外
  • 例外を処理する
  • 例外を送出する

構文エラー

構文エラーとは、Pythonプログラムの文法に違反した場合に発生するエラーです。Pythonのインタプリタはコードを順次解釈しますが、文法が正しくなければその場でエラーを報告します。プログラムは構文エラーがあると実行すらできません。

構文エラーの例と原因

  1. 括弧の閉じ忘れ
    Pythonでは括弧の開閉が正しくないとエラーになります。
print("こんにちは"  # 括弧が閉じられていないため構文エラー
  1. コロンの記述忘れ
    if文や関数定義の最後にコロンが必要ですが、これを忘れるとエラーになります。
if 5 > 3  # コロンがないため構文エラー
    print("5は3より大きいです")

注意点

構文エラーはエラー表示に基づいて修正することが大切です。Pythonのエラーメッセージは比較的わかりやすいため、エラー箇所を特定しやすいです。初学者はまず構文ルールを学び、IDE(統合開発環境)を利用してリアルタイムでエラーを検出する方法もおすすめです。

例外

例外とは、プログラムの実行中に発生するエラーのことです。構文エラーと異なり、コードの文法は正しいものの実行時に問題が発生した場合にスローされます。Pythonではゼロ除算やファイルの存在しないパスへのアクセスなどが例外の典型例です。

例外の例と原因

  1. ゼロ除算エラー (ZeroDivisionError)
    ゼロで割り算しようとすると例外が発生します。
num = 10
result = num / 0  # ZeroDivisionErrorが発生
print(result)
  1. ファイル読み込み時のエラー (FileNotFoundError)
    存在しないファイルにアクセスしようとすると例外が発生します。
with open("non_existent_file.txt", "r") as file:
    content = file.read()  # FileNotFoundErrorが発生

例外の扱い

例外は try-except ブロックを用いることで処理を続行できます。これにより、プログラムがクラッシュするのを防ぎます。また、必要に応じてエラー原因をログ出力するのも良い習慣です。

例外を処理する

プログラム実行中に発生する例外をそのまま放置すると、処理が中断してしまいます。Pythonでは try-except 文を使うことで例外を適切に処理し、プログラムの安定性を高めることができます。特にユーザー入力を扱う際や外部リソースへのアクセス時に役立ちます。

例外処理の基本的な使い方

  1. ゼロ除算エラーを処理する
    ユーザーがゼロを入力した場合でもプログラムがクラッシュしないよう例外処理します。
try:
    num = int(input("割る数を入力してください: "))
    result = 10 / num
    print(f"計算結果は {result} です")
except ZeroDivisionError:
    print("ゼロで割ることはできません")
  1. 複数の例外を処理する
    複数種類の例外が発生する場合、それぞれに対応するexceptブロックを用意します。
try:
    num = int(input("数値を入力してください: "))
    print(f"10を割った結果は {10 / num} です")
except ZeroDivisionError:
    print("ゼロで割ることはできません")
except ValueError:
    print("数値以外の入力はできません")

注意点

すべての例外を一括して処理する except Exception: は便利ですが、具体的なエラー原因がわからなくなるため、なるべく避けましょう。また、 elsefinally を組み合わせることで、より細かい制御も可能です。

例外を送出する

例外を送出することで、開発者が意図的にエラー状態を通知できます。通常、異常な動作を検知した場合に raise 文を使って例外を発生させます。カスタム例外クラスを作成することで、より柔軟なエラー制御が可能です。

例外送出の基本的な使い方

  1. 単純な例外送出
    入力値が負の数である場合に例外を送出します。
def calculate_square_root(num):
    if num < 0:
        raise ValueError("負の数の平方根は計算できません")
    return num ** 0.5

try:
    result = calculate_square_root(-9)
except ValueError as e:
    print(f"エラー発生: {e}")
  1. カスタム例外クラスを使う
    ユーザー独自のエラーを明示するためにカスタム例外を作成します。
class NegativeNumberError(Exception):
    pass

def check_number(num):
    if num < 0:
        raise NegativeNumberError("負の数は許可されません")

try:
    check_number(-5)
except NegativeNumberError as e:
    print(f"カスタム例外発生: {e}")

注意点

例外を送出する場合は、適切なエラークラスを選択することが重要です。また、ユーザーが理解できるようにエラーメッセージも丁寧に記述することを心がけましょう。

Python 3 エンジニア認定基礎試験(8章):エラーと例外(後半)

Python 3 エンジニア認定基礎試験(8章):エラーと例外(後半)
  • 例外の連鎖
  • ユーザー定義例外
  • クリーンアップ動作を定義する
  • 定義済みクリーンアップ処理
  • 複数の関連しない例外の送出と処理
  • ノートによって例外を充実させる

例外の連鎖

Pythonでは、ある例外が別の例外を引き起こすケースがあります。このような場合、例外の連鎖を明示することで、エラーの原因を追跡しやすくすることができます。デフォルトでは、Pythonは自動的に例外の連鎖をサポートしますが、 raise ... from ... 構文を使うことで明示的に連鎖を設定できます。

例外連鎖を明示する

たとえば、ファイル読み込み処理でエラーが発生した際、プログラム側で別のエラーを発生させたい場合があります。

def read_file(file_path):
    try:
        with open(file_path, 'r') as file:
            return file.read()
    except FileNotFoundError as e:
        raise ValueError("ファイルが見つかりません") from e

try:
    read_file("non_existent_file.txt")
except ValueError as e:
    print(f"エラー: {e}")

上記のコードでは、元の FileNotFoundError を保持しつつ、新たな ValueError を発生させています。 from e の部分が例外連鎖を明示する部分です。

デフォルトの例外連鎖を利用する

例外の連鎖は from を省略した場合でも自動的に行われます。

def divide_numbers(a, b):
    try:
        return a / b
    except ZeroDivisionError as e:
        raise RuntimeError("ゼロによる除算が発生しました")

try:
    divide_numbers(10, 0)
except RuntimeError as e:
    print(f"エラー: {e}")

この場合も、バックトレースを確認すると元の ZeroDivisionError が記録されています。

注意点

例外の連鎖を適切に使うことで、エラーの根本原因を把握しやすくなります。特に大規模なシステム開発では、デバッグの効率を大幅に向上させるため重要です。

ユーザー定義例外

Pythonでは標準的な例外クラスが多く用意されていますが、アプリケーションの要件に応じてカスタム例外を作成することもできます。カスタム例外を使うことでエラーの種類を明確にし、エラー処理を簡潔に整理することが可能です。

カスタム例外の作成

カスタム例外は、Pythonの組み込み Exception クラスを継承して作成します。

class InvalidAgeError(Exception):
    """年齢が無効な場合に送出する例外"""
    pass

def check_age(age):
    if age < 0:
        raise InvalidAgeError("年齢は負の値にできません")
    print(f"入力された年齢: {age}")

try:
    check_age(-5)
except InvalidAgeError as e:
    print(f"エラー: {e}")

このコードでは、負の年齢が入力された場合にカスタム例外 InvalidAgeError を送出します。

カスタム例外に独自の属性を追加する

エラー情報をより詳細にするために、カスタム例外に属性を追加することもできます。

class InvalidScoreError(Exception):
    def __init__(self, score):
        self.score = score
        super().__init__(f"スコアが無効です: {score}")

def check_score(score):
    if score > 100:
        raise InvalidScoreError(score)

try:
    check_score(150)
except InvalidScoreError as e:
    print(f"エラー: {e}")

このようにして、エラー内容を詳細に通知する仕組みを作ることができます。

注意点

カスタム例外を作りすぎるとエラー処理が複雑になるため、基本的にはPythonの標準例外を活用し、必要な場面でのみカスタム例外を導入するのが望ましいです。

クリーンアップ動作を定義する

プログラムでは、ファイルやネットワーク接続、データベース接続などの外部リソースを使用する場面が多々あります。これらのリソースは使用後に必ず解放する必要があります。Pythonでは finally ブロックや with 文を使うことでクリーンアップ動作を確実に行えます。

finally ブロックを使ったクリーンアップ

例外の有無に関わらず、リソース解放やログ記録などのクリーンアップ処理を実行します。

try:
    file = open("example.txt", "r")
    content = file.read()
    print(content)
except FileNotFoundError:
    print("ファイルが見つかりません")
finally:
    file.close()
    print("ファイルを閉じました")

上記のコードでは、例外が発生しても finally ブロック内でファイルが必ず閉じられます。

with 文による自動クリーンアップ

with 文を使うことで、リソース解放を自動化できます。これにより、コードが簡潔になります。

with open("example.txt", "r") as file:
    content = file.read()
    print(content)
# withブロック終了時に自動的にファイルが閉じられる

注意点

with 文はファイル操作以外にもデータベース接続やスレッド制御で活用されます。できる限り with 文を利用し、クリーンアップ漏れを防ぐことが推奨されます。 finally を使う場合でも、リソース解放が確実に行われるように注意しましょう。

定義済みクリーンアップ処理

プログラミングでは、ファイル操作やネットワーク接続、データベース処理など、使用したリソースを確実に解放することが重要です。Pythonでは、このようなクリーンアップ処理を定義済みの方法で効率よく行うために、with 文を活用できます。with 文を使うことで、明示的にリソースを解放するコードを書く必要がなくなり、エラー時にも自動で解放が行われます。

ファイル操作での定義済みクリーンアップ処理

ファイルを開いた後、閉じることを忘れるとリソースリークが発生する可能性があります。しかし、with 文を使用すると、ブロックを抜けるときに自動的にファイルが閉じられます。

# 定義済みクリーンアップ処理: ファイル操作
with open("example.txt", "r") as file:
    content = file.read()
    print(content)
# with ブロック終了時にファイルは自動的に閉じられる

このようなコードは、ファイルクローズ処理の漏れを防ぐため、特に推奨されます。

データベース接続での定義済みクリーンアップ処理

クリーンアップ処理はファイル以外にも適用できます。以下は、データベース接続を例にしたコードです。

import sqlite3

# データベース接続も定義済みクリーンアップ処理に対応
with sqlite3.connect("example.db") as conn:
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users")
    rows = cursor.fetchall()
    for row in rows:
        print(row)
# conn は自動的にクローズされる

注意点

クリーンアップ処理を忘れるとリソースが枯渇し、プログラム全体のパフォーマンスが低下します。with 文によるクリーンアップは、エラー発生時にも確実にリソースを解放するため、安全で効率的な方法です。開発時には、積極的にこの手法を取り入れることが推奨されます。

複数の関連しない例外の送出と処理

プログラムでは複数の異なる原因でエラーが発生することがあります。これに対処するため、Pythonでは一度に複数の例外を送出および処理する仕組みを提供しています。特に raise ... from ... を使用することで、異なる例外同士を関連付けることが可能です。

一度に複数例外を送出する

異なる原因の例外を一度に処理したい場合、次のように raise ... from ... を活用します。

def process_data(data):
    if not isinstance(data, list):
        raise TypeError("データはリストでなければなりません")
    if len(data) == 0:
        raise ValueError("データリストが空です")

try:
    process_data("")
except (TypeError, ValueError) as e:
    print(f"エラー発生: {e}")

このコードでは TypeError および ValueError を一括して捕捉します。

関連しない例外を独立して処理する

次に、複数の異なる例外を個別に処理する例です。

try:
    x = int("abc")
    y = 1 / 0
except ValueError:
    print("文字列を整数に変換できません")
except ZeroDivisionError:
    print("ゼロによる除算エラーです")

上記コードでは、ValueErrorZeroDivisionError をそれぞれ別のハンドラで処理します。

注意点

複数の例外を送出する際、適切なエラーハンドリングを行うことで、プログラムの信頼性を向上させられます。状況に応じて、例外を個別に処理するか、まとめて処理するかを使い分けることがポイントです。

ノートによって例外を充実させる

Python 3.11以降では、例外に「ノート」を付与する機能が導入されました。これにより、エラー情報をより詳細に提供し、デバッグやログ記録が容易になります。ノートを追加することで、エラーの発生状況や補足情報をプログラマーに伝えられるため、特に複雑なシステム開発で役立ちます。

ノートを追加する方法

BaseException クラスの add_note() メソッドを利用して、例外に補足情報を追加します。

try:
    raise ValueError("無効な入力です")
except ValueError as e:
    e.add_note("入力値は数値である必要があります")
    e.add_note("ヒント: 0~100の範囲で入力してください")
    raise

上記コードでは、ValueError に複数のノートを追加しています。エラー発生時に補足情報も表示されるため、デバッグが効率化されます。

実際の活用例

開発中のシステムで、APIエラーが発生した場合に詳細なノートを付けるケースです。

class APIError(Exception):
    pass

try:
    raise APIError("APIリクエストが失敗しました")
except APIError as e:
    e.add_note("エンドポイント: /user/data")
    e.add_note("ステータスコード: 500")
    raise

このように、API通信時の詳細情報を例外に追加することで、運用時のトラブルシューティングが容易になります。

注意点

ノート機能を使うことで、エラー情報を体系的に管理できます。ただし、ノートに依存しすぎるとエラー処理が複雑になるため、重要な情報のみを簡潔に記載することが望ましいです。

Python 3 エンジニア認定基礎試験(8章)の重要ポイントまとめ

  • 構文エラーは文法違反時に発生し、コード実行ができない
  • 括弧の閉じ忘れやコロンの記述漏れが構文エラーの典型例
  • 例外は実行時エラーであり、異常動作によりスローされる
  • ゼロ除算エラーやファイル読み込み失敗が代表的な例外
  • try-except 文で例外処理を行うことでプログラムの安定性が向上する
  • 複数の例外はそれぞれ異なる except ブロックで処理できる
  • except Exception の利用は具体的なエラー原因を隠すため注意が必要
  • raise 文を使うことで任意の例外を送出できる
  • カスタム例外クラスを作成することでエラー制御が柔軟になる
  • finally ブロックでリソースの解放やクリーンアップ処理を確実に行う
  • with 文は自動クリーンアップ処理を提供し、ファイルやDB操作で便利
  • 例外連鎖は from を使ってエラー原因を明示できる
  • Python 3.11 以降は例外にノート情報を追加可能になった
  • ノートはデバッグ支援やトラブルシューティングに有用な情報を付与する
  • クリーンアップ漏れはパフォーマンス低下につながるため注意が必要

タイトルとURLをコピーしました