0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

技術書一冊やり込もうAdvent Calendar 2024

Day 7

Pythonチュートリアル #6 -例外まみれ-

Last updated at Posted at 2024-12-06

※以下の企画です

今回は8章をやっていきます。
8章は「エラーと例外」というタイトルで、普段何気なくおまじない的に使っているtry/exeptあたりをちゃんと学べそうな気がしています。
それではやっていきますぅ。

8章 学習内容まとめ

そもそもエラーには2種類あり、構文エラー例外とのこと。
本章はそれらをそれぞれ学べる内容になっていた。

例外の処理

例外を待ち構える文法は「try / except」で書く。これはPythonに限らず様々な言語でサポートされている文法(try / catchの方が個人的には馴染みがあるが)
特に新しい学びはないかなーと思って読んでいたが、exceptはタプルで複数種類待ち構えられるというのは初めて知った。

複数種類のexcept
>> except(RuntimeError,TypeError,NameError):
>>   pass

また、try / exceptはオプションでelseをつけられる。
これはtryで例外が発生しなかった場合にジャンプする場所となっていて、tryにコードをつらつら書くのではなくelse句に書いていくことが推奨されていた。
try / exceptで本来プロテクトしなくて良い例外までキャッチしてしまうのを防ぐためらしい。これはたしかにそう。

try except else
>> try:
>>   print('try')
>> except:
>>   print('except')
>> else:
>>   print('else')

try
else

例外の送出

例外は意図的に送出もできる。これは自主的に使ったことが無かったものの、ちゃんと使えれば質の高いコードになるなと感じた。
方法は簡単でraiseを使うだけ。

raise
>> raise NameError('oops')

---------------------------------------------------------------------------
NameError                                Traceback (most recent call last)
<ipython-input-2-41bcb0d57fce> in <cell line: 1>()
----> 1 raise NameError('oops')

NameError: oops

exceptと組み合わせももちろん可能。

raise - except
>> try:
>>   raise NameError('oops!!!')
>> except NameError:
>>   print('例外だああああ!')
>>   raise


例外だああああ
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-c755c7cd20cd> in <cell line: 1>()
      1 try:
----> 2   raise NameError('oops!!!')
      3 except NameError:
      4   print('例外だああああ!')
      5   raise

NameError: oops!!!

この場合、except句内で引数なしのraiseを使用すると、現在処理中の例外(この場合は NameError)を再度発生させられる。
この仕様は本書だけだと読み取れなかったので、GPTに教えてもらった。
この処理を正しく使いこなせるかはわからないが、意識的に使えるよう脳に焼き付けておく…

クリーンアップ動作

try/except構文には、else意外に実はまだもう一つの文法がある(他にもあるかもだが、紹介されていたのはこれが最後)。
それがtry / excepyt / finally
finallytryが例外を送出しようがしまいが関係なく実行される。
elseは「例外が発生しなかった場合に処理される」ものであったので、この違いに注意したい。

finally句
>> def divide(x,y):
>>     try:
>>         result = x / y
>>     except ZeroDivisionError:
>>         print("division by zero!")
>>     else:
>>         print("result is", result)
>>     finally:
>>         print("finally!")

上記のようなコードであれば、上手く割り算できようが、ゼロ除算が起きようが、他のエラー(文字列が入力されたとか)が起きようが、finally句は実行される。

finally 実行結果
>> divide(1,2)

result is 0.5
finally!


>> divide(1,0)

division by zero!
finally!


>> divide("1","0")

finally!
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-598d3dd0ec63> in <cell line: 1>()
----> 1 divide("1","0")

<ipython-input-3-866838b2288c> in divide(x, y)
     1 def divide(x,y):
     2     try:
----> 3         result = x / y
     4     except ZeroDivisionError:
     5         print("division by zero!")

TypeError: unsupported operand type(s) for /: 'str' and 'str'

個人的には、大量のデータの書き出しとかに使えるんじゃないかなと思った。
ビッグデータの処理でCSVやらBigQueryやらに結果を格納していくときに、処理途中でエラー(想定外の無効な文字が入っていてとか)が生じた際に、finally句でそこまでの結果を書き出しておくみたいな。
エラー用にexcept句に書くよりもスマートに行けるんじゃないかなぁ。
これはぜひとも実務でも使ってみたい。

まとめ

僕の書くコードはエラーまみれの例外まみれなので、この章は非常に勉強になった。
特にfinallyはなんで今まで調べなかったのだろうと後悔しつつ、新たな学びになって良かったとも思う。
初心に戻る大切さを今更ながら痛感した…。
次回も楽しくやっていきます〜

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?