Python/Djangoやってて少しは例外処理に慣れてきた気がする
油断していると 500 エラーで落ちる
なんかちょっと機能をつくったり改修していたりすると、その場では動いても、なんらかの形でデグレったり違う改修によって入力される想定されるデータとは異なるものがはいってきたりする。なので、例外処理必要。油断しているとよく例外落とすのわすれて 500 エラー出したりなんか動かなくなったりして困るので、自分にとっての頻出パターンを振り返ってみた。
Django のインスタンス
たとえばこんな
Model.objects.get(pk=1) # Model.DoesNotExist Model.objects.all()[0] # IndexError
あるインスタンスをとってこようとするとそれがない場合は例外で落ちる。getはわかりやすくて「あー get するから一意になるように値をセットしないとなー」とか気をつけたりするから例外処理書き忘れることはすくないけど、filter でインデキシングでとってきたりするともちろんこれもインスタンスがないことがあるのでエラーですね。
date のパース
たとえばこんな
from datetime import date # YYYY-MM-DD のデータがはいってる!はず! _date = get_hoge_date _date = _date.split("-") # ValueError _date = date(int(_date[0]), int(_date[1]), int(_data[2])) # IndexError
はい、ありますね。ありますね。あったんですよ!!!!「ここにくるデータはYYYY-MM-DDで保証されている」という話なんだから「じゃー split("-") してインデックスつかえばええかー」と思ってると!、いつのまにか「YYYY-MM-DD HH:mm:SSになってるやないかァー!」「そもそも YYYY/MM/DD とかのパターンエラーを考えなきゃイカンやないかァー!」と。落ちます。つーかそもそもデータが空だったりします。おまえ、バリデーションしてたんじゃなかったのかァー!
はい。例外処理しましょう。
"""その昔な、YYYY-MM-DDの文字列を datetime object にしたかったんじゃよ""" from datetime import date data = get_hoge_date() if not data: return None try: # YYYY-MM-DD と YYYY-MM-DD hh:mm:SS に両方対応させる # ['2012', '02','01']みたいなリストになる _date = data.split(' ')[0].split('-') or data.split('-') # で、適応。int にするのを忘れずに date_object = date(int(_date[0]), int(_date[1]), int(_date[2])) except (ValueError, IndexError): return None return date_object
もうちょっとお利口にやるなら split やインデキシングのたびに try でかこったほうがいいのかもしれないけど、まあだからといって返すものも変わらないので今回はまとめた。わけて考えるならそうしましょう。
追記
@xxxxxxx より
日時の文字列をdatetimeオブジェクトに変換するときは datetime.datetime.strptime 使うといいですよ
お、そちらのほうが筋がよさそうですね。軽く試した(コピペしても動くかわからんがこんな感じ)
from datetime import datetime data = get_hoge_moge() if not data: return None try: # "2012-01-23 11:22:33" # YYYY-MM-DDがほしい data = data.split(" ") # セパレータを消す # YYYYMMDD data = data[0].replace("-", "") date_object = datetime.strptime(data, "%Y%m%d") except: return None return date_object