ホーム > Python > 初めてのPython(7) 例外に関する簡単なまとめ

初めてのPython(7) 例外に関する簡単なまとめ

先週はPHP Matsuriの準備と後片付けでPythonを勉強する時間が取れませんでした…。
かなりの時間を使ったと思うのですが、その分楽しめたと思います。
どんなイベント?“と少しでも興味があるかたはこちらを。

PHP Matsuriのまとめも書いていきたいのですが、その前に勉強したPythonの例外をまとめておきます。
忘れないうちにやっておかないと、綺麗さっぱり頭の中から消え去ってしまうので…。

ちょっと期間が空いてしまいましたが、Pythonの例外についてまとめます。

初めてのPython VII部

初めてのPythonのVII部には”例外“がまとめられています。
構文が中心に、少しだけその設計に関することも書かれています。

例外処理というのは奥が深いものです。
そもそも、簡単なWebアプリケーションを作っているだけでは、例外に触れる機会がありません
PHPもPythonも、簡単なアプリケーションでは設計者が気にしなくても、”良きに計らって“くれますからね。

それだけに、”エラーが起こりえる“プログラムを書くときにどう書けば良いかわからなくなってしまうんです。
簡単なWebアプリケーションから、より深い部分に触れるプログラムを書き始めたときにエラー処理さえ書かないこともしばしば(それは自分のことです :D)。

そういった”エラーが起こりえる状況への対処“を認識する上で、このVII部は重要だと思います。
どんなときに例外を使うのか、どんなときにtry,else,finalyの構文を使うのか。
初めてのPython“のVII部を読めば、このイメージをつかめます。

プログラマーとしてのレベルを上げるためにも読んでおきたいところです。

ここでは簡単な構文と、その動作についてまとめます。
例外の設計を語るほど、プログラマーとしてのレベルは高くないので…。

例外の種類

Pythonには2種類の例外があります。

  • 文字列例外
  • クラス例外

これらには、読んで字の通り、例外の内容が”文字列“か、”クラス“かの違いがあります。
コード数は”文字列例外“のほうが少なくなります。
しかし、色々と使い勝手が良いのは”クラス例外“です。

# 文字列例外
raise "This is Exception string."

# クラス例外
class EggException(BaseException): pass
raise EggException()

クラス例外は”クラス“を別に定義する必要がある分、コードが長くなります
文字列例外は”文字列“を例外として渡すだけなので、コードが短くなります

しかし、例外を捕まえ、事後処理をする場合の話は別です。
この場合、この二つの例外でコードの長さはほとんど変わりません
結局、同じロジックを書くことになるためです。
問題はどこにそのロジックを書くか。

# 文字列例外
stringException = "This is Exception"
try:
	raise stringException
except e:
	print "Got Exception."

# クラス例外
class ClassException(BaseException):
	def printException(self):
		print "Got Exception."

try:
	raise ClassException()
except ClassException, E:
	E.printException()

文字列例外では例外を捕まえる度にロジックを書きます
クラス例外ではクラスの1メソッドとして、ロジックを書いておき、そのメソッドを呼び出します
演算子のオーバーロードをうまく使えば、メソッドを呼び出す必要もありません。

ここで違いが出るのは、コードの見やすさですね。
クラスに例外処理を全てまとめることができ、見やすいコードが出来上がります。

その他には”関連する(継承した)クラスを捕まえることが出来る”こともクラス例外の特徴として上げられます。

# 親クラスの定義
class ParentClassException(): pass
# サブクラスの定義
class SubClassException(ParentClassException): pass

# 親クラスを指定して、サブクラスの例外を捕まえることが出来る。
try:
	raise SubClassException()
except ParentClassException:
	print "Got Exception."

そして、ここまで説明しておいて申し訳ないのですが、文字列例外は2.6以降のバージョンでは廃止されています
今まで見てきた通り、クラス例外のほうが使いやすいためです。
文字列例外は”簡単に書ける“こと以外にメリットがありませんから。
Pythonでは構文を統一させるために、こういった仕様変更がよく起こるようですね。

クラス例外では、これらの特性を利用して、色々な例外処理を設計出来そうです。
例外の設計を別に勉強したいですね。
アーキテクチャ系の本を読めば良いのかな?

例外を捕まえる

先ほどから簡単な例外を捕まえる例を書いています。
しかし、Pythonには他にも例外を取り扱う構文があります。

  • raise
    • 例外を発生させる。
  • assert
    • 条件が合致した場合にだけ、例外を発生させる。
  • try/except
    • tryの中で例外があった場合に、exceptのロジックを実行する。
  • try/finally
    • tryの中での例外の有無に関わらず、finalyのロジックを実行する。
  • with/as
    • コンテキストマネージャと呼ばれる高度な例外処理を実行する。

ここで重要な構文はraisetry/except、それにtry/finallyでしょう。

class EggException(BaseException):
  what = 'This is EggException'
class SpamException(BaseException):
  what = 'This is SpamException'

try:
	# この中で起こった例外が補足される。

	### 以下のいずれかのraiseのコメントを外して実行する。
	# EggExceptionのインスタンスを例外として投げる。
	#raise EggException() #これを実行すると、exceptの中が実行される。
	# SpamExceptionのインスタンスを例外として投げる。
	#raise SpamException() #これを実行すると、elseの中が実行される。
	# EggExceptionクラスのオブジェクトを例外として投げる。
	#raise EggException #これを実行すると、exceptの中が実行される。

	# 例外が発生した場合、ここは実行されない
	print 'Not execute'

# EggExceptionを補足する。他の例外は無視。補足した例外を変数eに入れる。
except EggException, e:
	print e.what

# BaseExceptionを継承した例外を補足する。補足した例外は変数eに入れる。
else BaseException, e:
	print e.what

# 例外の有無に関わらず、実行する。
finally:
	print 'every time'

これが基本形ですね。
例外として投げることが出来るのは、”オブジェクト“です。
従って、クラスのインスタンスやクラスそのものを投げることが出来ます。
先ほどの例では、”raise EggException”がこれにあたります。

そのため、先ほど”文字列例外は廃止された”と書きましたが、文字列のオブジェクトを例外として投げることは出来ます。

try:
	raise 'This is test.'
except:
	print 'Got Exception.'

その他に数字もOK。

try:
	raise 1000
except:
	print 'Got Exception.'

さらに、tryがない場合はどうなるのか?

“例外が発生したオブジェクトを呼び出しているオブジェクト”に例外が渡されます。

一番簡単な例はこれです。

def egg():
	raise BaseException

try:
	egg()
except:
	print 'Got Exception'

この例ではegg関数の中にtry/exceptはないのですが、それを呼び出しているメインモジュールにはtry/exceptがあります。
そのため、このメインモジュールで例外が補足されています。
これはどれだけネストが深くなっても同じです。
もちろん、クラスでも、モジュールでも。

python_exception.png

例外に関してはこんなところでしょうか。
もっと色々と説明したいのですが、長くなってしまいます。
詳しく知りたい方は是非、初めてのPythonを買ってください。

これで、Pythonの基礎は一通り終わりです。
次は指にPythonを慣れさせる段階ですね!

初めてのPython 第3版 初めてのPython

  • 著者: Mark Lutz (著), 夏目 大 (翻訳)
  • 出版社: オライリージャパン
  • 発売日: 2009/02/26

こちらもあわせてどうぞ

ちょっと一言

最近、ブログの更新を怠り気味。
今週から毎日、更新しようと思うのですが、早速障害発生してます。
土日に書き貯めておいてよかった...。

  • http://topsy.com/1-byte.jp/2010/10/11/learning_python7/?utm_source=pingback&utm_campaign=L2 Tweets that mention 初めてのPython(7) 例外に関する簡単なまとめ — Topsy.com

    [...] This post was mentioned on Twitter by sinwxyz and tfmagician(FUJIWARA), tfmagician(FUJIWARA). tfmagician(FUJIWARA) said: ブログ更新しました!: 初めてのPython(7) 例外に関する簡単なまとめ http://1-byte.jp/2010/10/11/learning_ [...]

blog comments powered by Disqus

ホーム > Python > 初めてのPython(7) 例外に関する簡単なまとめ

スポンサードリンク
書いている人
つぶやき
RSS 気になるニュース
過去の記事

ページの上部に戻る