[Python] 例外処理とループ処理を組み合わせた基本的な書き方

Pythonでは、例外処理とループ処理を組み合わせることで、エラーが発生してもプログラムを継続して実行することができます。

例外処理はtryexceptブロックを使用して行います。

ループ処理はforwhileを使用します。

ループ内で例外が発生した場合、exceptブロックでエラーをキャッチし、適切な処理を行うことが可能です。

これにより、特定のエラーが発生した際にループを中断せずに次の反復処理に進むことができます。

この記事でわかること
  • ループ内での基本的な例外処理の方法
  • 例外発生時のループの継続や終了の仕組み
  • ユーザー入力やファイル操作における例外処理の実践例
  • 複数の例外を同時に処理する方法
  • 非同期処理における例外処理の活用方法

目次から探す

例外処理とループ処理の組み合わせ

ループ内での例外処理の基本

Pythonでは、tryexceptを使用して例外処理を行います。

ループ内で例外処理を組み合わせることで、エラーが発生してもプログラムが停止せず、次のループに進むことができます。

以下は、基本的な例です。

for i in range(5):
    try:
        print(10 / i)  # 0で割ると例外が発生
    except ZeroDivisionError:
        print("0で割ることはできません。")

このコードを実行すると、0で割ることはできません。というメッセージが表示され、プログラムは正常に続行されます。

10.0
0で割ることはできません。
5.0
3.3333333333333335
2.5

例外発生時のループ継続

例外が発生した場合でも、ループを継続する方法を示します。

以下のコードでは、リスト内の数値を使って割り算を行い、例外が発生した場合はそのまま次の数値に進みます。

numbers = [10, 0, 5, 2]
for num in numbers:
    try:
        print(10 / num)
    except ZeroDivisionError:
        print("0で割ることはできません。")
10.0
0で割ることはできません。
2.0
5.0

例外発生時のループ終了

特定の条件で例外が発生した場合に、ループを終了させる方法もあります。

以下の例では、ValueErrorが発生した場合にループを終了します。

numbers = [10, 'a', 5, 2]
for num in numbers:
    try:
        print(10 / num)
    except (ZeroDivisionError, ValueError) as e:
        print(f"エラーが発生しました: {e}")
        break  # ループを終了
10.0
エラーが発生しました: unsupported operand type(s) for /: 'int' and 'str'

例外処理を用いた入力の検証

ユーザーからの入力を検証する際にも、例外処理が役立ちます。

以下のコードでは、ユーザーに数値を入力させ、無効な入力があった場合は再度入力を促します。

while True:
    try:
        user_input = int(input("数値を入力してください: "))
        print(f"入力された数値は: {user_input}")
        break  # 正常な入力があった場合はループを終了
    except ValueError:
        print("無効な入力です。数値を入力してください。")

このコードは、ユーザーが数値を入力するまで繰り返しプロンプトを表示します。

無効な入力があった場合は、エラーメッセージを表示し、再度入力を促します。

実践例

ファイル読み込み時の例外処理とループ

ファイルを読み込む際には、ファイルが存在しない場合や読み込みエラーが発生することがあります。

以下のコードでは、複数のファイルを読み込む際に例外処理を用いてエラーを処理し、次のファイルに進む方法を示します。

file_names = ["file1.txt", "file2.txt", "nonexistent.txt"]
for file_name in file_names:
    try:
        with open(file_name, 'r', encoding='utf-8') as file:
            content = file.read()
            print(f"{file_name}の内容:\n{content}")
    except FileNotFoundError:
        print(f"{file_name}が見つかりません。")
    except Exception as e:
        print(f"{file_name}の読み込み中にエラーが発生しました: {e}")

このコードは、存在しないファイルがあった場合でも、他のファイルの読み込みを続けます。

file1.txtの内容:
Hello, World!
file2.txtの内容:
Python is great!
nonexistent.txtが見つかりません。

ユーザー入力の検証と再入力要求

ユーザーからの入力を検証し、無効な入力があった場合に再度入力を促す方法を示します。

以下のコードでは、数値の入力を求め、無効な場合は再入力を要求します。

while True:
    try:
        user_input = int(input("整数を入力してください: "))
        print(f"入力された整数は: {user_input}")
        break  # 正常な入力があった場合はループを終了
    except ValueError:
        print("無効な入力です。整数を入力してください。")

このコードは、ユーザーが正しい整数を入力するまで繰り返しプロンプトを表示します。

APIリクエストのリトライ処理

APIリクエストを行う際に、接続エラーやタイムアウトが発生することがあります。

以下のコードでは、リクエストが失敗した場合にリトライを行う方法を示します。

import requests
import time
url = "https://api.example.com/data"
max_retries = 3
for attempt in range(max_retries):
    try:
        response = requests.get(url)
        response.raise_for_status()  # ステータスコードが200以外の場合は例外を発生
        print("データを取得しました:", response.json())
        break  # 正常に取得できた場合はループを終了
    except requests.exceptions.RequestException as e:
        print(f"リクエストに失敗しました: {e}")
        if attempt < max_retries - 1:
            print("再試行します...")
            time.sleep(2)  # 2秒待機
        else:
            print("最大リトライ回数に達しました。")

このコードは、APIリクエストが失敗した場合に最大3回までリトライを行います。

データベース操作の例外処理とループ

データベースに対する操作でも、例外処理が重要です。

以下のコードでは、複数のSQLクエリを実行し、エラーが発生した場合でも次のクエリに進む方法を示します。

import sqlite3
# データベースに接続
connection = sqlite3.connect('example.db')
cursor = connection.cursor()
queries = [
    "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)",
    "INSERT INTO users (name) VALUES ('Alice')",
    "INSERT INTO users (name) VALUES ('Bob')",
    "INVALID SQL QUERY",  # 無効なクエリ
    "INSERT INTO users (name) VALUES ('Charlie')"
]
for query in queries:
    try:
        cursor.execute(query)
        connection.commit()
        print(f"クエリ実行成功: {query}")
    except sqlite3.Error as e:
        print(f"クエリ実行中にエラーが発生しました: {e}")
# 接続を閉じる
connection.close()

このコードは、無効なSQLクエリがあった場合でも、他のクエリの実行を続けます。

応用例

複数の例外を処理するループ

Pythonでは、exceptブロックで複数の例外を同時に処理することができます。

以下のコードでは、リスト内の数値を使って割り算を行い、ZeroDivisionErrorValueErrorの両方を処理します。

values = [10, 0, 'a', 5, 2]
for value in values:
    try:
        result = 10 / value
        print(f"10 / {value} = {result}")
    except (ZeroDivisionError, ValueError) as e:
        print(f"エラーが発生しました: {e}")

このコードは、数値以外の値や0で割る場合にエラーメッセージを表示し、プログラムの実行を続けます。

10 / 10 = 1.0
エラーが発生しました: division by zero
エラーが発生しました: unsupported operand type(s) for /: 'int' and 'str'
10 / 5 = 2.0
10 / 2 = 5.0

ネストされたループと例外処理

ネストされたループ内で例外処理を行うことも可能です。

以下の例では、2次元リストの各要素に対して処理を行い、例外が発生した場合は内側のループをスキップします。

data = [[10, 5], [0, 2], ['a', 3], [4, 0]]
for row in data:
    for value in row:
        try:
            result = 10 / value
            print(f"10 / {value} = {result}")
        except ZeroDivisionError:
            print("0で割ることはできません。")
        except ValueError:
            print("無効な値が含まれています。")

このコードは、各行の値に対して割り算を行い、エラーが発生した場合はその値をスキップします。

10 / 10 = 1.0
10 / 5 = 2.0
0で割ることはできません。
10 / 2 = 5.0
無効な値が含まれています。
10 / 4 = 2.5
0で割ることはできません。

非同期処理と例外処理の組み合わせ

非同期処理を行う際にも、例外処理が重要です。

以下のコードでは、非同期関数を使用してAPIリクエストを行い、例外が発生した場合に適切に処理します。

asyncioaiohttpを使用しています。

import asyncio
import aiohttp
async def fetch_data(session, url):
    try:
        async with session.get(url) as response:
            response.raise_for_status()  # ステータスコードが200以外の場合は例外を発生
            return await response.json()
    except aiohttp.ClientError as e:
        print(f"リクエストに失敗しました: {e}")
async def main():
    urls = ["https://api.example.com/data1", "https://api.example.com/data2", "https://invalid.url"]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_data(session, url) for url in urls]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        for result in results:
            if isinstance(result, Exception):
                print(f"エラーが発生しました: {result}")
            else:
                print("データを取得しました:", result)
# 非同期処理を実行
asyncio.run(main())

このコードは、複数のURLに対して非同期でリクエストを行い、エラーが発生した場合はそのエラーを表示します。

非同期処理を使用することで、効率的にリクエストを行うことができます。

よくある質問

例外処理を使うべきタイミングは?

例外処理は、予期しないエラーが発生する可能性がある箇所で使用するべきです。

特に、ユーザー入力、ファイル操作、ネットワーク通信、データベース操作など、外部要因に依存する処理では、例外処理を用いることでプログラムの安定性を向上させることができます。

エラーが発生した場合でも、プログラムがクラッシュせずに適切に処理を行うことが重要です。

ループ内での例外処理のパフォーマンスへの影響は?

ループ内で例外処理を使用することは、通常の処理に比べてパフォーマンスに影響を与える可能性があります。

特に、例外が頻繁に発生する場合、例外処理のオーバーヘッドがパフォーマンスを低下させることがあります。

しかし、例外処理はエラーを適切に管理するための重要な手段であり、パフォーマンスと安定性のバランスを考慮することが大切です。

最適化が必要な場合は、例外が発生しないように事前に条件をチェックすることが推奨されます。

例外処理とエラーハンドリングの違いは?

例外処理は、プログラム内で発生するエラーを捕捉し、適切に処理するための構文(tryexceptなど)を指します。

一方、エラーハンドリングは、エラーが発生した際にどのように対応するかを含む広い概念です。

エラーハンドリングには、例外処理の他にも、エラーメッセージの表示、ログの記録、リトライ処理などが含まれます。

つまり、例外処理はエラーハンドリングの一部であり、エラーに対する具体的な対策を講じるための手段です。

まとめ

この記事では、Pythonにおける例外処理とループ処理の組み合わせについて詳しく解説しました。

例外処理を適切に使用することで、プログラムの安定性を向上させ、エラーが発生してもスムーズに処理を続けることが可能です。

今後は、実際のプログラムに例外処理を取り入れ、より堅牢なコードを書くことを目指してみてください。

  • URLをコピーしました!
目次から探す