見出し画像

Pythonのエラー処理を学ぼう【例外処理】

■ なぜエラー処理をするのか

今回は、Pythonのエラー処理(例外処理)について紹介します。

一度完成したプログラムは淀みなく動くものですが、たとえば「スクレイピング」を行うようなプログラムは時間の経過とともに動かなくなります
当然のことですよね。
WEBの世界はどんどん変化するものですから、WEBページが変化すればスクレイピングプログラムも変更が必要になるわけです。
その「変化」をいち早く察知し、修正するためにも、プログラムにはエラー処理の仕組みを用意しておく必要があります

プログラムを実用していくためには必須の知識ですので、ぜひこの機会にエラー処理の方法を習得してしまいましょう!


■ 環境設定

今回紹介するPythonプログラムの実行環境を紹介します。
Pythonの実行環境はGoogle Colaboratory(以下Colab)を使用します。
環境の作り方については、過去の記事にまとめていますので、そちらをごらんください
10分程度で作れてしまうので、ぜひ気軽に取り組んでみてください。


■ ステップ0:サンプルコード

Pythonのエラー処理を学ぶサンプルコードは以下の通りです ▼

l_stocklist = ["1301", "1306", "2121"]

for stockcode in l_stocklist:
    print(f"StockCode: {stockcode}")

非常にシンプルな内容ですが、多少の投資用語も含まれているのでポイントを以下にまとめておきます ▼

・「stockcode」は、日本の上場企業の証券コード(同じ数字は存在しない)
・「stocklist」は、投資銘柄のリスト
・「stocklist」に含まれる「stockcode」を順番に表示している

Colabへ貼り付けて実行すれば、3つの証券コードが順番に表示されるはずです。


■ ステップ1:最小限のエラー処理

まずは、最小限のエラー処理から押さえていきましょう。
以下のPythonプログラムは、必要最小限のエラー処理です ▼

import traceback

l_stocklist = ["1301", "1306", "2121"]

for stockcode in l_stocklist:

    try:
        """ 実行したい処理を書く
        """
        print(f"StockCode: {stockcode}")

    except Exception as e:
        """ 全てのエラーに対応する
        """
        print(type(e))
        print(traceback.format_exc())

先ほどのプログラムから、少し変化がありますね。
要点はプログラム内にコメントしている通りですが、まとめると以下の通りです ▼

・実行したい処理は「try:」ブロックにまとめる
・エラー対応(例外処理)は「except Exception:」ブロックにまとめる
・「type(e)」で例外の種類(例外クラス)を取得する
・「traceback.format_exc()」でエラー内容を取得する

実際には上記のプログラムでエラーは起きないのですが、まずは最も基本的な書き方を紹介しました。


■ ステップ2:意図的にエラーを出力する方法

先ほどのプログラムではエラーは出力されませんから、これではエラー処理の練習にはなりませんよね。
しかし、Pythonにはこういった練習やテストのためにも「意図的にエラーを出力する方法」が用意されています。
意図的にエラーを出力させたプログラムは以下の通りです ▼

import traceback

l_stocklist = ["1301", "1306", "2121"]

for stockcode in l_stocklist:
    
    try:
        """ 実行したい処理を書く
        """
        print(f"StockCode: {stockcode}")

        if stockcode != "2121":
            raise Exception("ミクシィ以外の銘柄です")
        elif stockcode == "2121":
            print("銘柄リストにミクシィが含まれています")
    
    except Exception as e:
        """ 全てのエラーに対応する
        """
        print(type(e))
        print(traceback.format_exc())

以上のプログラムをColabに張り付けて実行してみてください。
先ほどと異なり、今度はエラーが出力されたはずです。
前述のプログラムとほとんど一緒ですが、エラーを発生させている部分がどこか分かるでしょうか?
「try:」ブロックの中、「raise Exception()」で意図的にエラーを発生させています
この方法を用いることで、起こりそうなエラーを先回りして対応したり、プログラムのテストに活用することができます。
プログラムのポイントは以下の通りです ▼

・「証券コード2121(ミクシィ)」でなければ例外を出す
・「raise Exception()」で意図的にエラーを出力できる
・意図的なエラー出力は、開発やテストに活用できる


■ ステップ3:特定のエラーに対応する方法

先ほどエラーを出力する方法を紹介しましたが、「エラーにもいくつかの種類がある」ということを知っておく必要があります。
「複数のエラーを出力・対応する」プログラムは以下の通りです ▼

import traceback

l_stocklist = ["1301", "1306", "2121"]

for stockcode in l_stocklist:

    try:
        """ 実行したい処理を書く
        """
        print(f"StockCode: {stockcode}")
       
        if stockcode == "1301":
            raise ValueError("この銘柄は極洋です")
        elif stockcode != "2121":
            raise Exception("ミクシィ以外の銘柄です")
        elif stockcode == "2121":
            print("銘柄リストにミクシィが含まれています")
   
    except ValueError as e:
        """ 特定のエラーに対応する
        """
        print(type(e))
        print(traceback.format_exc())
   
    except Exception as e:
        """ 残りのすべてのエラーに対応する
        """
        print(type(e))
        print(traceback.format_exc())

少しだけプログラムが増えましたが、難しい処理は行っていません。
上記のプログラムのポイントは以下の通りです ▼

・「証券コード2121(ミクシィ)」が銘柄リストに含まれていなければ例外を出す
・条件別に、異なるエラーを発生させている
・エラー(例外クラス)別に異なる対応ができる

また、上記のプログラムはあくまで試験的にエラーを出しているので、「なぜValueErrorなのか」という部分は気にしないでください。
例外クラスは思い付きで書いております。
「様々な例外クラスを、意図的に出せる」ということをご理解いただければ十分です。


■ ステップ4:その他のエラー処理(finally, else)

基本的なエラー対応は、ここまで紹介した内容で実践できるはずです。
しかし、Pythonの例外処理には「finally」「else」といった条件分岐が用意されており、これを使うことでさらに細かいエラー処理が可能となります
「finally」「else」を用いたサンプルコードは以下の通りです ▼

import traceback

l_stocklist = ["1301", "1306", "2121"]

for stockcode in l_stocklist:

    try:
        """ 実行したい処理を書く
        """
        print(f"StockCode: {stockcode}")
        
        if stockcode == "1301":
            raise ValueError("この銘柄は極洋です")
        elif stockcode != "2121":
            raise Exception("ミクシィ以外の銘柄です")
        elif stockcode == "2121":
            print("銘柄リストにミクシィが含まれています")
    
    except ValueError as e:
        """ 特定のエラーに対応する
        """
        print(type(e))
        print(traceback.format_exc())
    
    except Exception as e:
        """ 残りのすべてのエラーに対応する
        """
        print(type(e))
        print(traceback.format_exc())
        
    else:
        """ エラーが無ければ実行される
        """
        print("ELSE")

    finally:
        """ エラーが無くても必ず実行される
        """
        print("FINALLY")

どのような条件で「finally」「else」が機能するのかは、プログラム内のコメントに記した通りです。
言葉で細かい解説をしても余計難しく感じてしまいますから、ぜひColabへプログラムを張り付けて、実際に動かしてみてください。
ここまで紹介した内容が、Pythonの基本的なエラー処理になります。


■ ステップ5:エラーを通知・ログ出力する方法

プログラミングの技術が身についてくると、プログラムを自動で動かすようになるはずです。
そんな時、エラーを通知したり、エラーログを出力しておくと、プログラムの修正を迅速に行うことができるようになります
まず、エラー通知やログ出力をどこに書くのか押さえておきましょう ▼

import traceback

l_stocklist = ["1301", "1306", "2121"]

for stockcode in l_stocklist:

    try:
        """ 実行したい処理を書く
        """
        print(f"StockCode: {stockcode}")

        if stockcode == "1301":
            raise ValueError("この銘柄は極洋です")
        elif stockcode != "2121":
            raise Exception("ミクシィ以外の銘柄です")
        elif stockcode == "2121":
            print("銘柄リストにミクシィが含まれています")

    except ValueError as e:
        """ 特定のエラーに対応する
        """
        # Line通知、ログ出力
        send_line_msg()
        logger.error(type(e))
        logger.error(traceback.format_exc())            

    except Exception as e:
        """ 残りのすべてのエラーに対応する
        """
        # Line通知、ログ出力
        send_line_msg()
        logger.error(type(e))
        logger.error(traceback.format_exc())    

エラー処理のブロックにコメントした「# Line通知、ログ出力」の部分に実行文を書きます。
(上記のプログラムはコピペしても動きません)

「Lineを使った通知方法」や「ログ出力の方法」については、近日中に紹介予定ですので、ぜひnoteをフォローしてお待ちいただけると嬉しいです^^

かじり虫の活動を応援してくださる方のサポート、お待ちしております。 これからも有意義なコンテンツを作成していきますので、私の「夢中」をぜひ一緒に共有していきましょう^^