数弱の文系大学生によるブログです。

Python、Webデザイン関連の記事を投稿していけたらなと思っています。

備忘録的なブログなので、読みにくい文章だと思います。ご了承ください。

Python3の復習(エラー処理:try・except)

こんにちは。

最近アルコ&ピースのラジオにハマっている、かにたまごです。
普段ラジオ聴きながら記事を書いているのですが、作業効率は若干落ちているのかな。
音楽に関してはこちらの論文記事に情報があったけど、ラジオに関してはどうなんだろう。
まぁ書いてるときにラジオで笑っちゃうこととかザラにあるし、ダメなんだろうな。


そんなことは置いておいて、今回は

  • エラー処理:try・except

について、復習していきたいと思います。


今までのPython3 復習履歴は以下の通り。

  1. 数値・文字列
  2. リスト・タプル
  3. 辞書・集合
  4. if文・while文・for文
  5. 内包表記
  6. 関数
  7. ジェネレータ
  8. デコレータ
  9. 名前空間とスコープ
  10. アンダーバー・アンダースコアの意味

エラー処理:try・except

アプリケーションなどでは、エラーが発生した際に処理が止まってしまうと使い物にならない。
また、エラーが起きた際にどう対処すべきなのかを明確に記述することは、ユーザーを困らせないためにも重要。

  • エラーの種類

こちらの記事によると、エラーには二種類あるようです。

  • 構文エラー
  • 例外

まず、構文エラーとは、文法に即していない記述をしてしまった場合に発生するエラー。

ルールに則っていない書き方をしているのだから、そりゃプログラムが動かないよってことですかね。

いわゆるSyntax Error。このエラーは死ぬほど見ます・・・。


次に例外は、文法的には正しいが実行時に予期せぬ自体が起こってしまった場合に発生するエラー。

例えば、数値での入力を期待していたのに文字列が入ってきてしまった場合とかですかね。

実行時に何かしらの処理が行われるので、ここで初めてエラーが発生するわけですね。


これは未然に防ぎたい・・・。


ということで、try・except等のエラー処理を行う必要があるってことです。

  • 使い方

こんな使い方で合っているかどうかわからないけど、一応書いてみた。

数値のみでの入力を想定しているパスワードの入力フォームの例。

while True:
    try:
        pswd = input("数値のみで構成されたパスワードを入力してください: ")
        if pswd == "":
            print("空白です。")
            continue
        length = len(str(pswd))
        pswd = int(pswd)
        check_pswd = "*" * length
        print("パスワードが入力されました: ", check_pswd)
        print("認証完了")
        break
    except KeyboardInterrupt as ki:
        print("\n中断されました")
        break
    except ValueError as vr:
        import re
        result = re.sub("[0-9]", "*", pswd)
        print("次の箇所に数値以外の文字が含まれています: ", result)
    except Exception as e:
        import traceback
        print("\nエラー情報:")
        traceback.print_exc()
        break

普通に数値のみを入力すると

数値のみで構成されたパスワードを入力してください: 573758237
パスワードが入力されました:  *********
認証完了

空白のままエンターキーを押すと

数値のみで構成されたパスワードを入力してください:
空白です。
数値のみで構成されたパスワードを入力してください:

数値以外の文字が入ったパスワードを入力すると

数値のみで構成されたパスワードを入力してください: 7492jh93h84392h
次の箇所に数値以外の文字が含まれています:  ****jh**h*****h
数値のみで構成されたパスワードを入力してください:

このように動作する。


実行時に発生したエラーを検知して、各エラーに対する処理を記述してあげる感じで大丈夫かな。

exceptのみで例外をキャッチすることもできるけど、推奨はされていないみたい。

while True:
    try:
        pswd = input("数値のみで構成されたパスワードを入力してください: ")
        if pswd == "":
            print("空白です。")
            continue
        length = len(str(pswd))
        pswd = int(pswd)
        check_pswd = "*" * length
        print("パスワードが入力されました: ", check_pswd)
        print("認証完了")
        break
    except:
        print("何かしらのエラーが発生")
数値のみで構成されたパスワードを入力してください: 47329l4982
何かしらのエラーが発生
数値のみで構成されたパスワードを入力してください:

こんな感じでも動くっちゃ動くけど、ユーザーにとっては

どんなエラーが起きてどう行動すべきなんだろう

という気持ちにさせてしまうため、不親切なコードだと思う。

上記のコードのように、数値で入力すべきことは分かっていても誤って小文字のLが入力されてしまった場合に気付きにくい。


それ以前にwhileから抜け出せねぇ( ^ω^)・・・


これが適切(なのか・・・?)なエラー処理をしているコードだと

数値のみで構成されたパスワードを入力してください: 47329l4982
次の箇所に数値以外の文字が含まれています:  *****l****
数値のみで構成されたパスワードを入力してください:

というように、どこがダメだったのかが一応分かる。

  • 独自例外

自分の目的に応じて例外を定義することも可能。
独自例外を定義する際は、 Exceptionクラスを継承したクラスを定義する。

Dの文字が入っているとエラーを発生させる例外の定義(誰得・・・)

class DError(Exception):
    pass

words = ["bird", "pig", "cat", "Dog"]
upper_word = []

for word in words:
    if "D" in word:
        raise DError(word)
    upper_word.append(word.upper())
print(upper_word)

実行するとこんな感じになる。

メインプログラムを実行した結果、DErrorというエラーが発生してそれに該当するキーワードがDogですよ

ってことで大丈夫かな。機能してはいるみたい。

Traceback (most recent call last):
  File "new_test.py", line 86, in <module>
    raise DError(word)
__main__.DError: Dog

ただ、このままだと処理が止まってしまい、 print(upper_word) まで実行されないので

先ほど学んだ try・except を追加してエラー処理をしてあげる。

class DError(Exception):
    pass

words = ["bird", "pig", "cat", "Dog"]
upper_word = []

for word in words:
    try:
        if "D" in word:
            raise DError(word)
        upper_word.append(word.upper())
    except DError as d:
        print("エラー箇所: ", d)
print(upper_word)

すると

エラー箇所:  Dog
['BIRD', 'PIG', 'CAT']

というように、最後まで実行される。

さらに適切な(なのか・・・?Part2)エラーメッセージを載せてあげると

class DError(Exception):
    def __init__(self, word):
        self.__message__ = word+"にDの文字が含まれています"

words = ["bird", "pig", "cat", "Dog"]
upper_word = []

for word in words:
    try:
        if "D" in word:
            raise DError(word)
        upper_word.append(word.upper())
    except DError as d:
        print("エラー文: ", d.__message__)
print(upper_word)

出力結果。

エラー文:  DogにDの文字が含まれています
['BIRD', 'PIG', 'CAT']

classの作り方とか、継承とか普段使ってないと抜けてるもんだなぁ・・・。

アプリ制作でtry・exceptは使ってたけど、細かくエラー処理を分けたりしてなかったから勉強になった。
今度、そのガバガバのエラー処理で動いてるアプリの解説記事書きます(;^ω^)


以上です。


参考にさせていただいたサイト:

Pythonの例外処理!try-exceptをわかりやすく解説!