PyCon JP 2026

raiseをやめて得たもの、失ったもの

数年前、本番で動く Python のモノリポで「raise は原則やめよう」と決めました。例外が前提の言語での逆張りと分かったうえで2年間貫いた結果を報告します。

raise の代わりに選んだのは、失敗を「直和型」で表すことです。社内では Result 型と呼びますが、Haskell の Either、値の不在を表す Optional/Maybe も仲間で、「結果は値かエラーのどちらか一方」を型で示す発想です。対して Go の (value, error) や例外は、両者を同時に返せる「直積型」です。

得たものは明確です。シグネチャだけで何で失敗するか分かり、try/except で例外を握りつぶす事故が減り、バグと業務エラーを型で分けたことで、直すべきものだけが通知に上がるようになりました。

一方で失ったものもあります。標準も外部もライブラリは例外を投げるので、コードは例外と直和型の境界で暮らしています。共通エラー型 AppError を作ってかえって苦しみ、transaction.atomic() が err でロールバックしない罠にもはまりました。原則は現場の都合で何度も書き換わりました。

バッチやデータ基盤なら握りつぶして再実行でも回りますが、オンラインの実運用アプリでは取りこぼしが事故になります。だからこそ型に乗せる価値が高い。効く場所と要る覚悟までお話しします。

このトークで話すこと

  • なぜ raise をやめたのか / 直和型(Result・Either・Optional)とは
  • 直和 vs 直積:例外・(value, error)・null と何が違うか
  • 得たもの・失ったもの(握りつぶし減・バグと業務エラー分離 ⇔ 例外境界・共通エラー型・トランザクションの罠)
  • まとめ:実運用アプリだからこそ効く理由と覚悟が要る場所

Tell us about your own experience with this topic

Recustomer という会社で、本番で動く Python のモノリポを開発しているチームの一員です。趣味のコードではなく、止まると事業に直接響く実運用プロダクトです。「raise はなるべく使わず、失敗は直和型で表す」という方針で2年間ずっとコードを書いてきました。Result 型、契約表明(assert / expect)、例外境界の集約を日々使い、ルールが現場でどう効いてどこで困るかを、使う側として体験してきました。

このトークで話せるのは、ルールを作った側ではなく、ルールの中で実装し続けた側だからです。最初の方針が現場の都合で何度も書き換わっていくのを、内側から見てきました。AppError の共通化で苦しんだり、transaction.atomic() が Result の err でロールバックしてくれない罠にはまったり。こういう失敗は全部、私自身がコードでぶつかったものです。今回はそれを題材に、きれいごとではない実運用の話をします。

What discussions can you have with attendees through this talk?

・raiseをやめた/減らした経験のある方と、移行で一番しんどかった場所(既存ライブラリの例外、トランザクション、テストあたり)を突き合わせて、「移行の痛点マップ」を一緒に作れたらと思っています。
・エラー型をどこまで共通化するかは意見が割れるところです。AppErrorのような共通型を使っている方、やめた方、それぞれの判断を聞いて、「入れる/入れないを分ける基準」を言語化したいです。
・Result型を使っていないチームの方とも話したいです。raiseのままで困っていないか、困るとしたらどこか。乗り換える価値があるラインを一緒に探りたいです。

The speaker's profile picture
加藤雅也