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

例外処理は面倒だけど 500 エラーはもっとこわい

プログラムの本質的なロジックは簡単だけど例外対応に追われることが多いって聞いたことがあるけど、こういうことなんですかネェー。ファイルや引数とって型チェックとかしだすともっと大変。まあ、そこらへんは静的型付け言語とかならよしなにできそうだけど。