Python : 例外処理 try/except/else/finally raise assert BaseException

Pythonの例外処理来ました!!
例外処理を初めていじったのはC++だったけれど、なんじゃこりゃ?こんなの要るのか?ifでいいよ。ifで。って最初思った。
でも、Javaを使ってみて、例外処理のありがたさが分かった。

Javaは特に、Eclipseがあると例外処理に関しては覚えやすかった。最初viで書いていたので、面倒なだけだったし・・・
おかげで、今PythonをIDLEとかviで書いているんだけれど、例外処理の有り難味が分かるよ。
C++はそれほどクリティカルな物でない限り、例外処理は要らないけれど
JavaもPythonも例外処理は、乗用するので、覚えておきましょう。
C++いじってたのは昔なのと、最近のソース余り見てないから、今だとC++でもかなり使っているのかな?

まず、最初に言っておこう。
Python2.5から、try/except/else/finallyが一緒に使えるようになった。
それまでは、
try/except
try/finally
のペアしか使えず、elseはどちらのペアにも使えたらしい。古いバージョンのPythonは弄ってないのであくまでもらしいで。
2.5だと気にしなくていいので、特に注意する必要性はないけれど、古いバージョンで動かさないといけなくなる場合もあるかもなので
一応、頭に止めておいたほうがいいかも。

更に言っておこう。
文字列例外は使うな。クラス例外を使うのだ。
Javaの例外がそうだけれど、例外にツリー構造を持たせる方向性にPythonが進んでいる。
C++の場合は、言語標準ではなく設計するときに例外もクラスとして設計するような・・・なんで、こいつだけ違うんだ?w
まあとにかく、Pythonでは文字列例外は将来的になくなるということだ。
詳細はこちら。PEP 352 PEP 348
また、Javaでは関数、クラスの外に例外を投げる時は、throwsが必要だけれど、Pythonの場合はそれが要りません。
なので、どいつがいつ例外を出すのかが、Javaと違い明確じゃないです。
その結果、例外がトップレベルまで飛んでしまうと、プロセスを終了してエラーメッセージを出します。
そこが一番注意するところかな。例外処理に関しては、elseがある事以外は、Javaの方が明らかに使い勝手が良いです。
まあ、exceptだけを書けば、全ての例外をキャッチできるのと、2.5以降なら、except BaseExceptionでも全ての例外をキャッチできる。
複数の例外をキャッチするときは、tupleとしてつなげるみたい。

except (TypeError, IndexError):
  pass

という感じ。

さて、今回の例外サンプルはこちら。

""" exception sample program """
class MyClass:
  pass

class MyClassException(BaseException):
  def __init__(self):
    BaseException.__init__(self)
    self.message = "MyClassExceptionMessage"

  def tryexcept(cls):
    try:
      c1.attr
    except AttributeError, data:
      print data
    else:
      print "else"
    finally:
      print "finally"

if __name__ == "__main__":
  print "--- 1st step ---"
  c1 = MyClass()
  tryexcept(c1)
  print "--- 2nd step ---"
  c1.attr = "value"
  tryexcept(c1)
  print "raise --- String Exception ---"
  myExcept = "Error"
  try:
    raise myExcept, "exception data"
  except myExcept, data:
    print data
    print "raise --- Class Exception ---"
    myClsExcept = MyClassException()

  try:
    raise myClsExcept
  except:
    print myClsExcept.message
    print "--- assert AssertException ---"
    myException = MyClassException()

  try:
    assert False, "assert error message"
    except AssertionError, data:
    print data

python exception.py での実行結果はこちら。
— 1st step —
MyClass instance has no attribute ‘attr’
finally
— 2nd step —
else
finally
raise — String Exception —
exception.py:33: DeprecationWarning: raising a string exception is deprecated
raise myExcept, “exception data”
exception data
raise — Class Exception —
MyClassExceptionMessage
— assert AssertException —
assert error message
python exception.py -O で実行すると、最後の行の assert error message がなくなります。
上から解説していくと、1st step 2nd step が、try/except/else/finallyの動きを表示したやつです。
ソース見れば直ぐに分かるかと。
最初に言ったように、StringExceptionを投げると一応注意書きが出ます。これは注意なので、処理は止まりません。
次に、BaseExceptionを継承して作った例外クラス。これは、pydoc BaseException で調べてみて、BaseException.messageが標準であるので、それを上書きしてます。公式サイトの英語のドキュメントとかも探してみたんだけれど、使い方が載っていないんだよね。まあ、見つけたらそのうち追加で書きます。
で、最後のassert statementは、
__debug__
というフラグがTrueの時だけ実行されます。これは、-O オプションを付けて実行すると、Falseになります。
また、assertの最初の部分は評価式を書き、結果がFalseの時に例外が投げられます。例外の形は、AssertionErrorで固定みたい。これも、探してみたんだけれど、イマイチ説明が少ない・・・その後ろにはデータを送るといった具合。
例外処理はこんなところかな。
これで、Pythonの基本編はお終い。次からは、標準ライブラリをやりたいけれど、そういうのは実際にアプリケーション組みながらの方が覚えられるので、そうしようかな。マルチスレッドだけは、別にやりたいけれどw
だって、Webアプリ作っていて、マルチスレッドってそんなに使わないような。今なら、Ajaxでそれっぽい事も出来る訳だし。

Leave a comment

0 Comments.

Leave a Reply


[ Ctrl + Enter ]

Spam Protection by WP-SpamFree