eljefeblog 

Any sufficiently advanced technology is indistinguishable from magic

programming python-basic-lectures

【基本を学ぶ9:超初学者向け】Pythonプログラミング入門【例外処理編】

Pythonプログラミング入門【例外処理編】




(初めからしっかり学びたい方はこちら↓↓)



このシリーズを最後まで学習することで
Pythonプログラマとして太い知識の主軸を積み上げる事ができます。
本シリーズでは全てを網羅しているのではなく、最低限必要な情報のみ
提供している為、処所超初心者の方には理解が難しい箇所があると思われます。



分からない箇所はその用語なり、エラーをググる力をつけましょう。
執念深く自分の理解していないポイントを追求する事で
今のあなたに必要な書籍、それに関連する様々な付加情報を手に入れる事ができるはずです。



本記事はPythonにおける例外について、
詳しく理解し実際に自作する内容となります。



悩むペン銀

これまでPythonを勉強してきて、様々な種類のエラーが存在することに気づいた。Pythonではどのようにしてこれらのエラーを処理することができるのだろう?上手に対処する方法を知りたいな。


本記事ではこのような疑問に答えていきます。



これまでエラーメッセージについて深く言及することはありませんでしたが、
シリーズを通し勉強を進めていくと実際に様々なエラーメッセージを目にしてきたでしょう。



Pythonにおいてエラーには大きく二つの種類が存在し、
『構文エラー(Syntax error)』『例外(Exception)』が挙げられ
この2つのエラーに対してそれぞれ対処法方法も異なります。




本記事ではこれらのエラーに対し基礎知識と対処方法について
学ぶことができる内容となっています。




本記事の内容

  • 構文エラーと例外に関する基礎知識
  • Pythonにおけるエラー・例外処理に関する方法








  • エラーとは何か?


    エラーとはコンピュータにおいて、プログラムが指定されたよう正常に動作出来ない
    との判断から、処理の中断および停止を行う状態
    の事を指します。


    プログラムを書いていると本当にたくさんのエラーに遭遇しますよね。


    Unix用語では;標準入力・標準出力・標準エラー出力があり
    それぞれ

    標準入力(stdin):ターミナル上における入力
    標準出力(stdout):ターミナル上における出力(e.g. print関数の出力等)
    標準エラー出力(stderr):基本的にはターミナル上における出力
    (ただし標準出力とは別の部類)



    といった定義がされています。

    今回は標準エラー出力に関するお話です。



    構文エラーと例外の違いについて



    構文エラー(SyntaxError)


    構文エラーとは『Pythonの文法的な間違いにより発生するエラー』のことです。
    致命的なエラーでありコードを修正する必要があります。


    例えば以下のようなエラーの事です。

    >>> a = 5
    >>> if a>5
    ...     print("a is greater than 5")
      File "<ipython-input-2-77b781a7dd19>", line 1
        if a>5
              ^
    SyntaxError: invalid syntax



    この場合2行目にあるように
    最終行にコロン(‘:’)を付け忘れていることがエラーの原因となっています。



    Pythonではパーサーがエラー個所を特定し、矢印でエラー個所の最初の位置を教えてくれます。(SyntaxErrorの上に表示されている矢印です)
    エラー文は英文で示され、矢印の個所で起こっている問題を明確に叙述します。


    この場合、エラー文を大まかに訳すると「Pythonにおいて妥当でない構文が検出された」という理由でSyntaxErrorが起こっているという解釈になります。

    (このようにエラー文は英語で述べられるため、
    英語が苦手な方は辞書app等を使って調べる必要があります。)
    (こればかりは避けられないので英語の勉強は自主的に行うようにしましょう。)



    他にも以下のような場合に構文エラーは発生します。

  • if文を書いているのにブロックをインデントしていない
  • 関数を定義しているのに()を書き忘れている


  • 基本的に構文エラーはうっかりミスが原因となる場合が殆どです。
    しかし冒頭でも触れましたがプログラムが基本的に100%停止する致命的なエラーとなります。
    このエラーを起こさない為に自分が初歩的なミスをしていないのか
    今一度自分の書いたコードを大まかに確認してみましょう。



    例外(Exception)


    一般的に例外とは『文法が正しくとも起こるエラー』のことを指します。
    このエラーは構文エラーほど致命的なエラーではなく、想定できる例外であればプログラムを中断させることなく続行させることも可能です。

    例えば以下のようなエラーが例外に相当します。

    >>> list_example[1,2,3,4]
    >>> list_example[5]
    ---------------------------------------------------------------------------
    IndexError                                Traceback (most recent call last)
    <ipython-input-9-b6adf5c99ae8> in <module>
    ----> 1 list_example[5]
    
    IndexError: list index out of range



    少し見ていくと、1行目に定義したリストは4つの要素を格納していますが
    2行目では5つ目の要素を指定していることが分かります。
    リスト内に5つ目の要素は存在しないため、IndexErrorの例外が発生している
    という状況です。


    他にも頻繁に発生する例外では

  • ValueError;  値が適切でないエラー
  • IndexError;  指定したインデックスが適切でないエラー
  • NameError; 宣言した変数名が適切でないエラー
  • TypeError;  型が適切でないエラー

  • 等があり例外は構文エラーに比べ比較的原因を特定し難く、
    時として予期していない例外はプログラム自体に甚大な悪影響を及ぼします

    故に

    ①その例外内容を予測、把握する事
    ②そして対象の例外を正しく対処する事

    これらのことが要求されるのです。



    基本的には例外が発生するとエラー文を出力し、
    プログラムの実行は停止されます。



    起こっている例外が想定されたものであり、
    その例外に対し対応の処理を行うコードを用意しておけば大抵の場合問題ありません。
    正しい対処方法を身につけておきましょう。


    例外が発生した場合の対処方法


    tryとexceptについて



    例外が発生した場合、どのような処理を行うべきなのか。
    Pythonでは基本的にtry-except文を活用し例外処理を行います
    以下のように定義します。

    >>> try:
    ...     実行したい処理(例外が発生する可能性あり)
    ... except エラー名:
    ...     上記した「実行したい処理」において例外が発生した場合に行う処理



    この場合、tryブロック内で指定された処理が初めに実行されます。
    この実行中にexceptキーワードの後に指定されたエラー名と一致する例外が検出された場合、
    exceptブロック内で指定された処理が実行されるという流れです。



    このようにtry-except文を挿入することにより
    あるコードの実行にあたり特定の例外が検出された場合
    それが事前に意図したものであれば対処を講じることができ
    エラーとなってプログラムが停止することを避けれるのです。



    少し例をみてみましょう。

    >>> x=[1,2,3,4]
    >>> x[5]
    ---------------------------------------------------------------------------
    IndexError                                Traceback (most recent call last)
    <ipython-input-54-df3e65441209> in <module>
    ----> 1 x[5]
    
    IndexError: list index out of range
    



    例えば指定したインデックスがリストの外出会った場合
    上記のように例外IndexErrorが検出されプログラムは停止してしまいます。



    そこでtry-except文を利用して以下のように記述するとどうなるでしょうか?

    >>> x = [1,2,3,4]
    >>>
    >>> try:
    ...     y = x[5]
    ... except IndexError:
    ...     print("YOU CAN NOT APPOINT THE INDEX")
    ... print("LIST LENGTH: ",len(x))
    ...
    YOU CAN NOT APPINT THE INDEX
    LIST LENGTH: 4



    事前にindexErrorになる可能性がある部位において
    try-except文を挿入しておくことでプログラムを停止させることなく7行目の
    print関数を実行できることが確認できるでしょう。



    小さなプログラムではこの恩恵を感じにくいですが
    大きなプロジェクトに取り組む中でこの有り難さを理解できるようになるはずです。
    是非頭の片隅に入れておきましょう。



    例外発生後の処理(exceptブロック)



    意図して例外を発生させるraise


    例えばあなたがアプリケーションを作ったとして
    メールアドレスやアカウント名の入力を要求するとします。
    加えてメールアドレスの欄には入力値として.comで終わる文字列を想定していたとしましょう。

    その場合、例えば次のような例外が想定されます。

  • 日本語が入力されていたり
  • 入力された文字列が異常に長い
    (明らかにメールアドレスでない)
  • .jpで終わる文字列が入力された


  • この他にもプログラマーが想定していない様々な例外が発生します。
    予期していない入力があった場合、
    最悪のケースでは予期しないプログラムの誤作動が懸念されるでしょう。


    こういったことを未然に防ぐ意味でもraiseを挿入することで
    ユーザーの入力の段階において、後々誤作動を起こす前に強制的に
    例外を発生させ、プログラマに知らせることが可能です。




    例外が発生しなかった場合のelse
    例外の発生に関わらず必ず処理を実行させるfinal



    結論から述べると


    例外が発生しなかった場合に行う処理を宣言する場合はelse
    例外の有無に関わらず処理を実行したい場合finally


    を利用します。
    概要は以下です。

    >>> try:
    ...     実行したい処理(例外が発生する可能性あり)
    ... except エラー名:
    ...     上記した「実行したい処理」において例外が発生した場合に行う処理
    ... else:
    ...     上記した「実行したい処理」において例外が発生しなかった場合の処理
    ... finally:
    ...     例外が発生しようがしなかろうが、確実に実行される処理     
    



    それではこれらの概念を踏まえ少し例を見てみましょう。

    >>> def inspectCalculation(salary, time):
    ...        try:
    ...            hourlySalary = salary*time
    ...        except ZeroDivisionError:
    ...            print("ゼロでは割れません")
    ...        else:
    ...            print("時給: ",hourlySalary)
    ...        finally:
    ...            print("時給の計算を終了します")
    ...            


    このtryブロックでの計算ではtimeに0を指定すると
    ZeroDivisionErrorが発生すると予測されます。


    実際に指定した場合の結果は以下のようになります。

    >>> inspectCalculation(30000,0)
    ゼロでは割れません
    時給の計算を終了します


    exceptブロックで指定した文章が
    プリントされていると確認できるでしょう。


    それでは正しい整数値を引数として渡してみましょう。

    >>> inspectCalculation(30000,4)
    時給: 7500.0
    時給の計算を終了します。



    例外が発生することなく計算が行われ、
    exceptブロックで定義したprint関数が実行されていません。


    代わりにfianallyブロックで定義した文章がprintされていると確認できるでしょう。



    まとめ



    いかがだったでしょうか?

    今回はPythonにおける例外処理に関して知識を深めていく内容でした。
    ぜひ例外処理という存在がある事を頭に入れておきましょう。


    そしてPythonでのプログラミングをある程度習得した段階で
    もう一度更に詳しく勉強してみましょう。


    今回はここまでにしておきます。
    ではでは





    人気記事【初学者必見】効率的なプログラミング勉強方法を紹介します

    人気記事 CS学位取得者がガチでプログラミングスクールを調査してみた件【おすすめのスクール】




    続編はこちら↓





    このエントリーをはてなブックマークに追加
    data-ad-format="rectangle" data-ad-format="rectangle"

    返信する

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

    某国立大学大学院(理系)に所属しています。 最近の趣味は人工知能関連の論文を読む事で 研究ではComputer Vision周りを中心に活動しており、 サイドワークとしてデータ分析の業務に関わっています。 本ブログはこれまで筆者が学んできた様々な知識の中から 有益だと思えた情報のみをまとめたものです。 内容は個人の見解であり、所属する機関と関係するものではありません。 Research: is related to Computer Vision Hobby: is to study Artificial Intelligence / Machine Learning.