Python学習【365日チャレンジ!】270日目のマスターU(@Udemy11)です。
最近、車の中ではいつも坪田信貴氏の「才能の正体」を聴いています。
数少ない著者が朗読をするオーディオブックで、AmazonのAudibleの無料体験でゲットしました。
もうどのくらい繰り返したかわかりませんが、本の内容がかなり頭の中に入ってくる上、まるで坪田さんと知り合いになった感じがしてくるので、オーディオブックは超お勧めです。
ハリーポッターと死の秘宝と謎のプリンスの英語朗読版も聴いていたのですが、これまた英語の勉強になるのでやっぱりAudibleはお勧めです。
1冊の本の値段が高いのですが、無料体験で1冊ダウンロードしたあと解約すればずっと聴くことができるので、ぜひ無料体験してみてください。
それでは今日もPython学習を始めましょう。
昨日の復習
昨日は、stdout
とstderr
を使ったファイル出力を学習しました。
どちらもシステムのストリームで値を保持するので、そのまま出力することも可能でしたが、contextlib.redirect_stdout
やcontextlib.redirect_stderr
を使ってファイルに値を書き出すことが可能でした。
詳細は昨日の記事をごらんください。
今日は、例外処理に関するExitstack
を学習します。
例外処理で処理を分岐
try-except
文を使うことでエラーによる条件分岐を扱うことができましたが、エラーが起こっても起こらなくても処理をさせるやり方がtry-finally
文です。
try-finally
文を使ったコードを書いてみましょう。
def is_ok_job():
try:
print('Do something')
return True
except Exception:
return False
def cleanup():
print('Clean up')
try:
is_ok = is_ok_job():
print('More tasks')
finally:
if not is_ok:
cleanup()
復習がてら、このコードを読み解いてみてください。
参考までに出力結果は次のようになります。
出力結果
Do something
More tasks
1行目から6行目の関数is_ok_job
は、Do something
と出力したあと、True
を返すか、エラーが起こってFalse
を返す関数です。
8行目の関数cleanup
は、Clean up
を出力する関数です。
11行目からの実行コードは、関数is_ok_job
の返り値を変数is_ok
に代入して、More tasks
を出力したあと、is_ok
がFalse
の場合のみ、関数Clean up
を実行します。
上記のコードでは、エラーが起こってis_ok_job
の返り値がFalse
にはならないため、関数cleanup
は実行されません。
4行目にraise Exception('Error')
を挿入してエラーを起こさせると出力結果は、最後にClean up
の出力が追加されます。
出力結果
Do something
More tasks
Clean up
ExitStack
このtry-finally
文とおなじ処理をすることができるのが、contextlib.ExitStack
です。
import contextlib
def is_ok_job():
try:
print('Do something')
return True
except Exception:
return False
def cleanup():
print('Clean up')
with contextlib.ExitStack() as stack:
stack.callback(cleanup)
is_ok = is_ok_job()
print('More tasks')
if is_ok:
stack.pop_all()
最初にcontextlib
をインポートして、3行目から11行目までは同じコードを記述しています。
13行目14行目でwith
ステートメントでcontextlib.ExitStack
を使い、最後に実行する関数cleanup
をcallback
に入れています。
16行目、17行目は先ほどのコードと一緒です。
19行目で、変数is_ok
がTrue
かどうかを判断して、True
の場合は、stack.callback
をpop_all
で空にします。
出力結果
Do something
More tasks
このコードの場合、is_ok
がTrue
になっているので、stack.callback
が空になって関数cleanup
が実行されないので、Clean up
は出力されていません。
try-finally
のときと同じように、6行目にraise Exception('Error')
を挿入すれば、エラーが起こってis_ok
がFalse
となるので、stack.callback
に入れられた関数cleanup
が実行され、Clean up
が最後に出力されます。
出力結果
Do something
More tasks
Clean up
まとめ
コードを読み解くのはほんとパズルみたいな感じがしますが、すべてのコードが理解できて一連の流れがつながったときは、ボーリングでストライクを取ったときのような快感を感じることができます。
理解できないときは、ストライクスポットに入っているのに、なぜか1本だけ残ってしまい、スペアすらとれないもどかしさを感じてしまいます。
プログラミングはボーリングのように体力を使わないので、ボーリングと違って何度でも繰り返して試すことができますので、納得いくまで何度も実行してみてください。
今回はpop_all
がstack.callback
に入れた関数を空にするのではなく、すべて実行すると勘違いしてしまい、ちょっと戸惑ってしまいました。
でもpop
は、リストでも値を取り出して解放していたことを思い出せたので、早いうちに間違いに気づくことができました。
ほんと復習は大切ですね。
ということで、明日もGood Python!