0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonの例外処理を1から解説

Posted at

はじめに

Pythonには例外処理の書き方がいくつかあります。

この記事では、例外処理の基本となるtry-except構文、ファイル操作などでお馴染みのwith文を紹介し、最後にコンテキストマネージャについて解説します。

Pythonコード多め・文章少なめです。

例外処理について初歩の初歩から始まり、Python独自の書き方まで解説します。

例外とは

IndexErrorやValueErrorなど、コードを動かすとエラーを起こすことがあります。これを 例外 と呼びます。

lst = [2, 4, 6, 8]
element = lst[4]  # IndexError (リストの範囲外を見に行っているため)
word = "Python"
value = int(word)  # ValueError (アルファベットをint型にしようとしたため)

try-except構文

try節, except節

例外が出るかもしれないとき、例外を出して急に終了しないようにしたいです。

try-exceptをつかえば、例外が出たときの対応も書けます。

import logging


lst = [2, 4, 6, 8]
idx = 4

try:
    # 例外が出るかもしれない処理
    element = lst[idx]
    print(f"lstの{idx}番目の値は{element}です。")
except IndexErroe:
    # IndexErrorが出たときの処理
    logging.error({len(lst)=}, but {idx=}")

finally節

finally節を入れることもできます。この節では最後に必ず行う処理を書きます。

ファイルを開いたりデータベース接続をしたりした後、そのリソースを閉じるときによく使われます。

file_path = "test.txt"
file = None

try:
    file = open(file_path, 'r')  # ファイルを開く
    content = file.read()  # ファイルを読み込む
    print(content)
except FileNotFoundError:
    print(f"Error: {file_path} not found.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
finally:
    # 最後に開いたファイルを閉じる
    if file is not None:
        file.close()

else節

最後にelse節を入れることもできます。この節では、try節が正常終了したときの処理を書きます。

else節をうまく使うと、可読性が向上します。

file_path = "test.txt"
file = None

try:
    file = open(file_path, 'r')  # ファイルを開く
except FileNotFoundError:
    print(f"Error: {file_path} not found.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
else:
    content = file.read()  # ファイルを読み込む
    print(content)
    file.close()
finally:
    print("called finally.")

with文

今度はデータベース接続をしたときのことを考えてみます。

import sqlite3

conn = None
try:
    conn = sqlite3.connect('example.db')  # データベースに接続
    cursor = conn.cursor()
except sqlite3.Error as e:
    print(f"An error occurred: {e}")
else:
    # ここに100行以上の処理が入る (今回は省略)
finally:
    if conn is not None:
        conn.close()

else節にとても長いコードが入ることもあります。そんな中、本当にfinally節でちゃんと接続を閉じられるでしょうか?

そのようなことを防ぎコードを簡潔にしたのが 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.close() のようにデータベース接続を閉じなくても、with節を抜けたら自動で閉じてくれます。

ファイルを開くときにもよく使われます。

try:
    with open(file_path, 'r') as file:
        content = file.read()
        print(content)
except FileNotFoundError:
    print("File not found.")

with文を使うと、try, finallyの処理を簡潔に書けます。

コンテキストマネージャ

open関数のように、with文に入れられるものを コンテキストマネージャ と呼びます。

自作することもできます。

自作クラス

with節に入るときの処理は def __enter__(), with節から出るときの処理は def __exit__() に書きます。

main.py
class MyContextManager:
    def __enter__(self):
        print("Entering context")
        return "MyContextManager returned"

    def __exit__(self, exc_type, exc_value, exc_traceback):
        print("Exiting context")


with MyContextManager() as cm:
    print("with", cm)
出力結果
Entering context
with MyContextManager returned
Exiting context

contextmanagerデコレータ

クラスよりも簡潔に自作できるのがcontextmanagerデコレータです。

from contextlib import contextmanager

@contextmanager
def my_context_manager():
    print("Entering context")
    yield "MyContextManager returned"
    print("Exiting context")

with my_context_manager() as cm:
    print("with", cm)
出力結果
Entering context
with MyContextManager returned
Exiting context

with節に入るときに、yield よりも前に書いた処理が呼ばれます。
cmの値は yield で返す値です。
with節から出るときに、yield よりも後に書いた処理が呼ばれます。

おわりに

ファイル操作やデータベース接続など、例外処理を使う場面は多いです。
これらの技術を適切に活用することで、コードの安全性と可読性が向上します。

参考文献

O'REILLY - Effective Python

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?