<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>raise  |  Python-memo｜自動化・AI・Web開発の実験室</title>
	<atom:link href="https://python.cbagames.jp/tag/raise/feed/" rel="self" type="application/rss+xml" />
	<link>https://python.cbagames.jp</link>
	<description>Pythonで、できるをふやそう。</description>
	<lastBuildDate>Mon, 22 Dec 2025 10:56:51 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://python.cbagames.jp/wp-content/uploads/2025/06/cropped-497d491d54402de785c9e043bfa0620a-32x32.png</url>
	<title>raise  |  Python-memo｜自動化・AI・Web開発の実験室</title>
	<link>https://python.cbagames.jp</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Pythonの例外を「投げる側」設計ベストプラクティス｜raiseの判断基準と失敗しない流儀</title>
		<link>https://python.cbagames.jp/2025/12/22/python-exception-raise-best-practices/</link>
					<comments>https://python.cbagames.jp/2025/12/22/python-exception-raise-best-practices/#respond</comments>
		
		<dc:creator><![CDATA[asukapy]]></dc:creator>
		<pubDate>Mon, 22 Dec 2025 10:56:50 +0000</pubDate>
				<category><![CDATA[クラス設計・OOP入門]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[raise]]></category>
		<category><![CDATA[エラーハンドリング]]></category>
		<category><![CDATA[カスタム例外]]></category>
		<category><![CDATA[デバッグ]]></category>
		<category><![CDATA[例外処理]]></category>
		<category><![CDATA[設計]]></category>
		<guid isPermaLink="false">https://python.cbagames.jp/?p=705</guid>

					<description><![CDATA[Pythonでコードを書いていると、必ず向き合うことになるのが例外処理です。でも実際のところ、「try / exceptは書いているけど、raiseする側の設計はあまり意識していない」という方、多いんじゃないでしょうか。 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Pythonでコードを書いていると、必ず向き合うことになるのが<strong>例外処理</strong>です。<br>でも実際のところ、「try / exceptは書いているけど、raiseする側の設計はあまり意識していない」という方、多いんじゃないでしょうか。</p>



<p>例外というと「エラーが起きたときの後始末」というイメージを持たれがちですが、Pythonではそれだけではありません。<br><strong>例外は、プログラムの制御構造の一部</strong>であり、設計次第でコードの読みやすさや保守性、デバッグ効率まで大きく変わります。</p>



<p>特に問題になりやすいのが、</p>



<ul class="wp-block-list">
<li>とりあえず <code>ValueError</code> を投げている</li>



<li>エラーメッセージが抽象的で原因が分からない</li>



<li>例外を投げ直したら元の情報が消えてしまった</li>
</ul>



<p>こうした状態が積み重なると、あとからコードを読む自分や、チームメンバーが「なぜ失敗したのか」を追えなくなってしまいます。 例外をどう<strong>捕まえるか</strong>以前に、<strong>どう投げるか</strong>がとても大切なんですね。</p>



<p>この記事では、Pythonの<strong>「例外を投げる（送出する）側」</strong>に焦点を当てて、</p>



<ul class="wp-block-list">
<li>どの例外型を選ぶべきか</li>



<li>メッセージや属性はどう設計するとよいか</li>



<li>例外の連鎖で文脈をどう残すか</li>
</ul>



<p>といったポイントを、思想 → 手順 → 実践の順で整理していきます。</p>



<p>「この <code>raise</code>、本当にこれでいいのかな？」と一度でも感じたことがあるなら、きっと役に立つはずです。 一緒に、<strong>読んだ人にやさしい例外設計</strong>を身につけていきましょう😊</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>




  <div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2"><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">1. なぜ「例外を投げる側」の設計が重要なのか</a></li><li><a href="#toc2" tabindex="0">2. Pythonにおける例外設計の基本原則（思想編）</a><ol><li><a href="#toc3" tabindex="0">EAFP原則：例外は“想定された流れ”の一部</a></li><li><a href="#toc4" tabindex="0">Fail-Fast：問題は起きた瞬間に止める</a></li></ol></li><li><a href="#toc5" tabindex="0">3. 手順1：適切な例外型を選ぶ（設計の第一歩）</a><ol><li><a href="#toc6" tabindex="0">組み込み例外を優先する理由</a></li><li><a href="#toc7" tabindex="0">カスタム例外を定義すべきタイミング</a></li><li><a href="#toc8" tabindex="0">カスタム例外設計の基本ルール</a></li><li><a href="#toc9" tabindex="0">例外を階層化するという発想</a></li></ol></li><li><a href="#toc10" tabindex="0">4. 手順2：例外メッセージと属性の設計</a><ol><li><a href="#toc11" tabindex="0">良い例外メッセージの基本</a></li><li><a href="#toc12" tabindex="0">メッセージだけに頼らない設計</a></li><li><a href="#toc13" tabindex="0">__init__設計と互換性の考え方</a></li></ol></li><li><a href="#toc14" tabindex="0">5. 手順3：例外の連鎖（Chaining）で文脈を失わない</a><ol><li><a href="#toc15" tabindex="0">raise ... from ... の役割</a></li><li><a href="#toc16" tabindex="0">例外をラップする理由</a></li><li><a href="#toc17" tabindex="0">from None を使うケース</a></li></ol></li><li><a href="#toc18" tabindex="0">6. 応用：Python 3.11以降の例外設計テクニック</a><ol><li><a href="#toc19" tabindex="0">ExceptionGroup：複数の失敗をまとめて伝える</a></li><li><a href="#toc20" tabindex="0">add_note()：後から情報を補足する</a></li><li><a href="#toc21" tabindex="0">assertとの正しい使い分け</a></li></ol></li><li><a href="#toc22" tabindex="0">7. まとめ：良い例外設計は「失敗の伝え方」の設計</a><ol><li><a href="#toc23" tabindex="0">あわせて読みたい</a></li><li><a href="#toc24" tabindex="0">参考文献</a></li></ol></li><li><a href="#toc25" tabindex="0">よくある質問（Q&amp;A）</a></li></ol>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">1. なぜ「例外を投げる側」の設計が重要なのか</span></h2>



<p>Pythonの例外処理というと、多くの場合は <code>try / except</code> の書き方から学び始めます。 もちろんそれも大切なのですが、実務でコードが読みにくくなる原因は、<strong>例外をどう捕まえたか</strong>よりも、<strong>例外をどう投げたか</strong>にあることが少なくありません。</p>



<p>例外は単なる「エラー通知」ではなく、<strong>プログラムの流れを分岐させるための明確なシグナル</strong>です。 つまり、if文やreturnと同じく、制御構造の一部として扱うべき存在なんですね。</p>



<p>ところが、送出側の設計を意識せずに書かれた例外には、次のような問題が起きがちです。</p>



<ul class="wp-block-list">
<li>どこで・なぜ失敗したのかが例外から分からない</li>



<li>呼び出し側が「どう対処すればいいのか」判断できない</li>



<li>デバッグ時にスタックトレースを追い続ける羽目になる</li>
</ul>



<p>たとえば、どんなエラーでも <code>ValueError</code> を投げてしまうと、 「値が悪いこと」以上の情報は失われます。 ファイルが存在しないのか、フォーマットが不正なのか、状態が不整合なのか―― <strong>本来は送出側が一番よく分かっているはずの情報</strong>が、そこで消えてしまうんです。</p>



<p>結果として、呼び出し側では</p>



<ul class="wp-block-list">
<li>とりあえず全部キャッチする</li>



<li>ログを見ないと原因が分からない</li>



<li>想定外の例外でアプリが落ちる</li>
</ul>



<p>といった「後追い対応」が増えていきます。 これは設計の問題であって、Pythonや例外そのものが悪いわけではありません。</p>



<p>逆に言えば、<strong>例外を投げる側が「何が起きたのか」「なぜ失敗したのか」を正確に伝えられれば</strong>、 呼び出し側のコードは驚くほどシンプルになります。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、こうした設計を支えているPythonの考え方として、 <strong>EAFP原則</strong>と<strong>Fail-Fast</strong>という2つの重要な思想を整理していきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc2">2. Pythonにおける例外設計の基本原則（思想編）</span></h2>



<p>例外を「どう投げるか」を考えるうえで、まず押さえておきたいのが、 Pythonが前提としているエラー処理の思想です。 ここを理解していないと、「なぜここでraiseするのか」「なぜifで防がないのか」が曖昧になってしまいます。</p>



<p>Pythonの例外設計を支えている代表的な考え方が、次の2つです。</p>



<ul class="wp-block-list">
<li>EAFP（Easier to Ask Forgiveness than Permission）</li>



<li>Fail-Fast（早期失敗）</li>
</ul>



<h3 class="wp-block-heading"><span id="toc3">EAFP原則：例外は“想定された流れ”の一部</span></h3>



<p>EAFPは、「許可を得るより、許しを請う方が早い」というPythonらしい設計思想です。 事前にすべてをチェックするよりも、まず処理を実行し、<strong>問題が起きたら例外で分岐する</strong>、という考え方ですね。</p>



<p>たとえば、</p>



<ul class="wp-block-list">
<li>値が正しいかをifで細かく確認してから処理する</li>



<li>実行してみて、ダメだったらraiseする</li>
</ul>



<p>この2つを比べたとき、Pythonでは後者が自然とされる場面が多くあります。 そのため、例外は「想定外の事故」ではなく、<strong>設計された異常系</strong>として扱われます。</p>



<h3 class="wp-block-heading"><span id="toc4">Fail-Fast：問題は起きた瞬間に止める</span></h3>



<p>Fail-Fastは、エラー条件をできるだけ早く検出し、 <strong>それ以上処理を続けず、すぐに失敗させる</strong>という考え方です。</p>



<p>例外を投げる側の視点では、</p>



<ul class="wp-block-list">
<li>「この状態で処理を続ける意味はあるか？」</li>



<li>「後続処理に任せて安全か？」</li>
</ul>



<p>を判断し、危険だと分かった時点でraiseします。</p>



<p>これにより、</p>



<ul class="wp-block-list">
<li>無駄な処理が走らない</li>



<li>不整合な状態が広がらない</li>



<li>原因が発生した場所で分かる</li>
</ul>



<p>というメリットが生まれます。 <strong>失敗を早く、正確に伝える</strong>ことは、例外設計の最重要ポイントと言ってもいいですね。</p>



<p>こうしたPython的な思想を体系的に理解したい場合、 設計原則を具体例と一緒に整理してくれる書籍はとても参考になります。</p>



<p><strong>Effective Python 第3版</strong><br><a rel="noopener" target="_blank" href="https://amzn.to/3Y7LtWw">✅ Amazonでチェックする</a>｜ <a rel="noopener" target="_blank" href="https://a.r10.to/h5KRCR">✅ 楽天でチェックする</a></p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章からは、こうした思想を踏まえたうえで、 実際に<strong>どのような手順で例外を設計・送出していくのか</strong>を具体的に見ていきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc5">3. 手順1：適切な例外型を選ぶ（設計の第一歩）</span></h2>



<p>例外設計で最初に考えるべきなのが、 <strong>「どの例外型を投げるか」</strong>です。 ここを雑にしてしまうと、どれだけ丁寧なメッセージを書いても、意図が正しく伝わりません。</p>



<p>基本的な考え方はとてもシンプルです。 <strong>まずは組み込み例外を使い、それで表現できない場合にだけカスタム例外を作る</strong>、これが王道です。</p>



<h3 class="wp-block-heading"><span id="toc6">組み込み例外を優先する理由</span></h3>



<p>Pythonには、よくある失敗パターンを表すための例外が、最初から豊富に用意されています。</p>



<ul class="wp-block-list">
<li><code>ValueError</code>：値は型的に正しいが内容が不正</li>



<li><code>TypeError</code>：型が期待と違う</li>



<li><code>IndexError</code>：インデックス範囲外</li>



<li><code>KeyError</code>：存在しないキーへのアクセス</li>
</ul>



<p>これらを使う最大のメリットは、<strong>見ただけで状況が想像できる</strong>ことです。 Pythonを書き慣れた人なら、例外型を見た瞬間に「何が起きたか」の方向性が分かります。</p>



<p>逆に、すべてを独自例外にしてしまうと、</p>



<ul class="wp-block-list">
<li>例外の意味を毎回調べる必要がある</li>



<li>exceptでの分岐が複雑になる</li>
</ul>



<p>といった負担が増えてしまいます。 まずは<strong>標準で表現できないか</strong>を考えるのが大切です。</p>



<h3 class="wp-block-heading"><span id="toc7">カスタム例外を定義すべきタイミング</span></h3>



<p>では、どんなときにカスタム例外を作るべきなのでしょうか。 目安は、<strong>そのエラーが「ドメイン固有の意味」を持つかどうか</strong>です。</p>



<p>たとえば、</p>



<ul class="wp-block-list">
<li>業務ルール違反</li>



<li>アプリケーション特有の状態不整合</li>



<li>外部APIとの契約違反</li>
</ul>



<p>こうしたエラーは、<code>ValueError</code>だけでは意図が伝わりません。 その場合に、意味のある名前を持つカスタム例外が活きてきます。</p>



<h3 class="wp-block-heading"><span id="toc8">カスタム例外設計の基本ルール</span></h3>



<p>カスタム例外を作る際には、いくつか守るべきルールがあります。</p>



<ul class="wp-block-list">
<li><strong><code>Exception</code>（またはそのサブクラス）を継承する</strong></li>



<li><strong><code>BaseException</code>を直接継承しない</strong></li>



<li>クラス名は <code>○○Error</code> で終わらせる</li>
</ul>



<p><code>BaseException</code>は、<code>SystemExit</code> や <code>KeyboardInterrupt</code> のように、 プログラム全体の終了に関わる例外のための基底クラスです。 通常のアプリケーション例外では、必ず <code>Exception</code> 側を使います。</p>



<h3 class="wp-block-heading"><span id="toc9">例外を階層化するという発想</span></h3>



<p>少し規模の大きいプロジェクトでは、 <strong>プロジェクト専用の基底例外クラス</strong>を用意しておくと便利です。</p>



<p>たとえば、</p>



<ul class="wp-block-list">
<li>MyAppError（基底）</li>



<li>ConfigError</li>



<li>ValidationError</li>
</ul>



<p>といった形で整理しておけば、</p>



<ul class="wp-block-list">
<li>個別にexceptできる</li>



<li>まとめてexceptすることもできる</li>
</ul>



<p>という柔軟なエラーハンドリングが可能になります。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、こうして選んだ例外型に対して、 <strong>どんなメッセージや情報を持たせるべきか</strong>を詳しく見ていきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc10">4. 手順2：例外メッセージと属性の設計</span></h2>



<p>適切な例外型を選んだら、次に重要になるのが <strong>「その例外が何を伝えるか」</strong>です。 同じ例外型でも、メッセージや持たせる情報次第で、読み手の理解度は大きく変わります。</p>



<p>例外メッセージは、人間に向けた<strong>最初の説明文</strong>です。 ログやトレースバックを開いたとき、真っ先に目に入るのがこの部分ですね。</p>



<h3 class="wp-block-heading"><span id="toc11">良い例外メッセージの基本</span></h3>



<p>まず意識したいのは、<strong>「何が」「なぜ」起きたのかが分かること</strong>です。</p>



<p>たとえば、次の2つを比べてみてください。</p>



<ul class="wp-block-list">
<li><code>raise ValueError("invalid value")</code></li>



<li><code>raise ValueError(f"user_id must be positive, got {user_id}")</code></li>
</ul>



<p>後者であれば、</p>



<ul class="wp-block-list">
<li>どの値が問題なのか</li>



<li>どんな条件を満たしていないのか</li>
</ul>



<p>が一目で分かります。 <strong>送出側が知っている情報は、できるだけ失わずに渡す</strong>のが理想です。</p>



<p>慣例としては、</p>



<ul class="wp-block-list">
<li>小文字で始める</li>



<li>末尾にピリオド（.）を付けない</li>
</ul>



<p>といった書き方がよく使われます。 厳密なルールではありませんが、コードベース内で統一しておくと読みやすくなります。</p>



<h3 class="wp-block-heading"><span id="toc12">メッセージだけに頼らない設計</span></h3>



<p>例外に情報を持たせる方法は、文字列だけではありません。 <strong>構造化されたデータ</strong>として属性を持たせることもできます。</p>



<p>たとえば、次のようなカスタム例外です。</p>



<pre class="wp-block-code"><code>
class ValidationError(Exception):
    def __init__(self, field, value, message):
        super().__init__(message)
        self.field = field
        self.value = value
</code></pre>



<p>これにより、呼び出し側では</p>



<ul class="wp-block-list">
<li>メッセージを表示する</li>



<li>fieldごとに処理を分ける</li>



<li>ログに構造化して出力する</li>
</ul>



<p>といった柔軟な対応が可能になります。</p>



<h3 class="wp-block-heading"><span id="toc13">__init__設計と互換性の考え方</span></h3>



<p>カスタム例外で <code>__init__</code> を定義する場合、 将来の拡張や互換性も意識しておくと安心です。</p>



<p>特に意識したいのが、<strong>Liskov置換原則</strong>です。 サブクラスに置き換えても問題なく動く、という考え方ですね。</p>



<p>そのためには、</p>



<ul class="wp-block-list">
<li><code>*args</code> / <code>**kwargs</code> を受け取れるようにする</li>



<li><code>super().__init__(*args)</code> を呼ぶ</li>
</ul>



<p>といった形を意識すると、 シリアライズ（pickle）や将来の拡張で困りにくくなります。</p>



<p>例外を「ただのエラー通知」ではなく、 <strong>設計された情報の入れ物</strong>として扱う、という発想はとても大切です。</p>



<p>こうしたクラス設計としての例外の考え方を、 より深く理解したい場合は、Pythonの言語仕様や設計思想を掘り下げた資料が役に立ちます。</p>



<p><strong>Fluent Python</strong><br><a rel="noopener" target="_blank" href="https://amzn.to/4p7TTbt">✅ Amazonでチェックする</a>｜ <a rel="noopener" target="_blank" href="https://a.r10.to/hNSatG">✅ 楽天でチェックする</a></p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、例外を投げ直すときに <strong>「なぜ失敗したのか」という文脈を失わないためのテクニック</strong>を見ていきます。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc14">5. 手順3：例外の連鎖（Chaining）で文脈を失わない</span></h2>



<p>実務のコードでは、低レイヤーで発生した例外を、そのまま上位に投げるのではなく、 <strong>意味を補足した別の例外に変換して送出したい</strong>場面がよくあります。</p>



<p>このときに重要になるのが、<strong>例外の連鎖（chaining）</strong>です。</p>



<h3 class="wp-block-heading"><span id="toc15">raise ... from ... の役割</span></h3>



<p>Pythonでは、次のように書くことで例外を連鎖させることができます。</p>



<pre class="wp-block-code"><code>
try:
    load_config(path)
except OSError as e:
    raise ConfigError(f"failed to load config: {path}") from e
</code></pre>



<p>この書き方のポイントは、</p>



<ul class="wp-block-list">
<li>上位の文脈に合った例外型に変換できる</li>



<li>元の例外（<code>OSError</code>）のトレースバックが保持される</li>
</ul>



<p>という点です。 スタックトレースを見ると、「何が直接の原因だったのか」まで辿れるため、 デバッグ効率が大きく向上します。</p>



<p>単に</p>



<pre class="wp-block-code"><code>
raise ConfigError("failed to load config")
</code></pre>



<p>としてしまうと、 <strong>なぜ失敗したのかという情報が完全に失われる</strong>点には注意が必要です。</p>



<h3 class="wp-block-heading"><span id="toc16">例外をラップする理由</span></h3>



<p>例外をラップするのは、情報を隠すためではありません。 <strong>責務の境界を明確にするため</strong>です。</p>



<p>低レイヤーでは</p>



<ul class="wp-block-list">
<li>ファイルが存在しない</li>



<li>権限がない</li>



<li>フォーマットが壊れている</li>
</ul>



<p>といった技術的な失敗が起きますが、 上位レイヤーでは「設定ファイルの読み込みに失敗した」という <strong>意味のある失敗</strong>として扱いたいことが多いですよね。</p>



<p>その橋渡しをするのが、例外の連鎖です。</p>



<h3 class="wp-block-heading"><span id="toc17">from None を使うケース</span></h3>



<p>場合によっては、元の例外情報が</p>



<ul class="wp-block-list">
<li>ユーザーに見せるべきでない</li>



<li>情報が多すぎて混乱を招く</li>
</ul>



<p>といったこともあります。</p>



<p>その場合は、</p>



<pre class="wp-block-code"><code>
raise ValidationError("invalid input") from None
</code></pre>



<p>とすることで、 元の例外のトレースバックを意図的に隠すことができます。</p>



<p>ただし、これは<strong>本当に必要な場合だけ</strong>に留めるのが大切です。 デバッグ時に使えない情報まで消してしまうと、 後から原因を追うのが非常に大変になります。</p>



<p>例外の連鎖を正しく使うことで、 <strong>「何が起きたか」だけでなく「なぜ起きたか」</strong>を コードとして正確に伝えられるようになります。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p>次の章では、Python 3.11以降で追加された <strong>少し発展的な例外設計テクニック</strong>を紹介します。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc18">6. 応用：Python 3.11以降の例外設計テクニック</span></h2>



<p>ここまでは、Pythonのバージョンに大きく依存しない、 例外送出の基本設計を見てきました。</p>



<p>この章では、Python 3.11以降で追加・強化された機能を使って、 <strong>「より情報量の多い例外」を投げるための応用テクニック</strong>を紹介します。</p>



<h3 class="wp-block-heading"><span id="toc19">ExceptionGroup：複数の失敗をまとめて伝える</span></h3>



<p>並行処理やバッチ処理では、 複数の独立した処理が同時に失敗することがあります。</p>



<p>こうした場合に便利なのが <code>ExceptionGroup</code> です。</p>



<pre class="wp-block-code"><code>
errors = &#91;]
for task in tasks:
    try:
        run(task)
    except Exception as e:
        errors.append(e)

if errors:
    raise ExceptionGroup("multiple tasks failed", errors)
</code></pre>



<p>これにより、</p>



<ul class="wp-block-list">
<li>最初の1件だけでなく、すべての失敗を報告できる</li>



<li>呼び出し側で <code>except*</code> を使って分類できる</li>
</ul>



<p>といった、これまで難しかった表現が可能になります。</p>



<h3 class="wp-block-heading"><span id="toc20">add_note()：後から情報を補足する</span></h3>



<p>Python 3.11では、すべての例外に <code>add_note()</code> メソッドが追加されました。</p>



<pre class="wp-block-code"><code>
try:
    process(data)
except Exception as e:
    e.add_note(f"input size: {len(data)}")
    raise
</code></pre>



<p>このようにすると、 トレースバックの最後に補足情報が表示されます。</p>



<p>ポイントは、</p>



<ul class="wp-block-list">
<li>例外型やメッセージを変えずに情報を足せる</li>



<li>デバッグ用の文脈を安全に追加できる</li>
</ul>



<p>という点です。 「raiseし直したいが、情報は足したい」という場面でとても便利です。</p>



<h3 class="wp-block-heading"><span id="toc21">assertとの正しい使い分け</span></h3>



<p>例外設計の話をしていると、 <code>assert</code>との使い分けで迷うことがあります。</p>



<p>基本的な役割は次の通りです。</p>



<ul class="wp-block-list">
<li><code>assert</code>：開発時の内部整合性チェック</li>



<li><code>raise</code>：実行時に起こり得る失敗の通知</li>
</ul>



<p><code>assert</code>は最適化オプションで無効化される可能性があるため、 ユーザー入力の検証や、回復可能なエラーには向いていません。</p>



<div class="wp-block-cocoon-blocks-balloon-ex-box-1 speech-wrap sb-id-1 sbs-stn sbp-l sbis-cb cf block-box not-nested-style cocoon-block-balloon"><div class="speech-person"><figure class="speech-icon"><img decoding="async" src="https://python.cbagames.jp/wp-content/uploads/2025/06/9d9697ea94c9608a27d0bde31599ba86-150x150.jpg" alt="" class="speech-icon-image"/></figure><div class="speech-name"></div></div><div class="speech-balloon">
<p><strong>「本番でも必ず守られるべき条件かどうか」</strong>を基準に、 raiseとassertを使い分けるのが安全です。</p>
</div></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2494518121553371"
     crossorigin="anonymous"></script><br />
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-2494518121553371"
     data-ad-slot="2936039508"></ins><br />
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></p>



<h2 class="wp-block-heading"><span id="toc22">7. まとめ：良い例外設計は「失敗の伝え方」の設計</span></h2>



<p>ここまで、Pythonにおける<strong>「例外を投げる（送出する）側」</strong>の設計について、 思想から具体的な手順、応用テクニックまで順番に見てきました。</p>



<p>改めて重要なポイントを整理すると、次の3つに集約できます。</p>



<ul class="wp-block-list">
<li>例外はエラー処理ではなく、制御構造の一部である</li>



<li>例外型・メッセージ・文脈をセットで設計する</li>



<li>「何が起きたか」だけでなく「なぜ起きたか」を伝える</li>
</ul>



<p>とりあえず例外を投げて、呼び出し側で何とかする―― このやり方は、短期的には楽でも、コードが育つにつれて必ず歪みが出てきます。</p>



<p>逆に、送出側でしっかりと設計された例外は、</p>



<ul class="wp-block-list">
<li>呼び出し側のコードをシンプルにする</li>



<li>ログやデバッグを圧倒的に楽にする</li>



<li>チーム開発での認識ズレを減らす</li>
</ul>



<p>という形で、後からじわじわ効いてきます。</p>



<p>例外設計は、Python特有のテクニックというより、 <strong>「失敗をどう扱うか」という設計思想そのもの</strong>です。</p>



<p>この考え方を、Pythonに限らず設計全般に広げたい場合は、 言語を超えて通用する視点を与えてくれる一冊が参考になります。</p>



<p><strong>Clean Code</strong><br><a rel="noopener" target="_blank" href="https://amzn.to/3MGnqvx">✅ Amazonでチェックする</a>｜ <a rel="noopener" target="_blank" href="https://a.r10.to/hFfpij">✅ 楽天でチェックする</a></p>



<p>ぜひ、次に <code>raise</code> を書くときは、</p>



<ul class="wp-block-list">
<li>この例外型で本当に伝わるか？</li>



<li>呼び出し側はどう受け取るか？</li>
</ul>



<p>を少しだけ意識してみてください。 それだけで、コードの質は確実に一段上がります✨</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><span id="toc23">あわせて読みたい</span></h3>



<p>例外設計の理解をさらに深めたい方は、次の記事もあわせて読むのがおすすめです。 「送出側」の考え方と組み合わせることで、エラーハンドリング全体が立体的に見えてきます。</p>



<ul class="wp-block-list">
<li><a target="_blank" href="https://python.cbagames.jp/2025/06/17/python-raise-exception/">Pythonのraise文とは？意図的に例外を発生させる方法と使いどころを解説！</a></li>



<li><a target="_blank" href="https://python.cbagames.jp/2025/06/12/python-traceback-how-to-read/">Pythonのトレースバック(traceback)の読み方と活用法｜エラー解析の基本</a></li>



<li><a target="_blank" href="https://python.cbagames.jp/2025/06/10/python-logging-basic-guide/">Pythonログ出力の基本をやさしく解説｜printとの違いとlogging入門</a></li>



<li><a target="_blank" href="https://python.cbagames.jp/2025/12/18/python-logging-design-best-practices/">Pythonログ設計の実践テクニック｜loggingを現場で使いこなす</a></li>



<li><a target="_blank" href="https://python.cbagames.jp/2025/06/13/python-pytest-beginner-guide/">Pythonでテストコードを書く方法｜pytest入門ガイド</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><span id="toc24">参考文献</span></h3>



<ul class="wp-block-list">
<li><a rel="noopener" target="_blank" href="https://docs.python.org/3/tutorial/errors.html">Python公式ドキュメント：Errors and Exceptions（例外処理チュートリアル）</a></li>



<li><a rel="noopener" target="_blank" href="https://docs.python.org/3/library/exceptions.html">Python公式ドキュメント：Built-in Exceptions（組み込み例外一覧）</a></li>



<li><a rel="noopener" target="_blank" href="https://realpython.com/python-raise-exception/">Real Python：Pythonで例外をraiseする方法と設計の考え方</a></li>



<li><a rel="noopener" target="_blank" href="https://zenn.dev/kyonaka/articles/7224c826dff629">Zenn：Pythonの例外設計を整理する（カスタム例外・raiseの考え方）</a></li>



<li><a rel="noopener" target="_blank" href="https://qiita.com/CRUD5th/items/56e507f0650031e36de0">Qiita：Pythonの例外処理まとめ（基礎から設計視点まで）</a></li>



<li><a rel="noopener" target="_blank" href="https://metana.io/blog/mastering-python-exception-handling-best-practices-for-try-except/">Metana：Mastering Python Exception Handling – Best Practices</a></li>



<li><a rel="noopener" target="_blank" href="https://stackoverflow.com/questions/57165380/when-should-i-declare-custom-exceptions">Stack Overflow：いつカスタム例外を定義すべきか？</a></li>



<li><a rel="noopener" target="_blank" href="https://stackoverflow.com/questions/1319615/how-do-i-declare-custom-exceptions-in-modern-python">Stack Overflow：モダンなPythonでのカスタム例外定義方法</a></li>



<li><a rel="noopener" target="_blank" href="https://beagle-dog.com/python-exception-handling/">BeagleDog Blog：Python例外処理の基本と実践</a></li>



<li><a rel="noopener" target="_blank" href="https://www.geeksforgeeks.org/python/python-exception-handling/">GeeksforGeeks：Python Exception Handling</a></li>
</ul>



<h2 class="wp-block-heading"><span id="toc25">よくある質問（Q&amp;A）</span></h2>



<div class="wp-block-cocoon-blocks-faq faq-wrap blank-box block-box not-nested-style cocoon-block-faq"><dl class="faq"><dt class="faq-question faq-item"><div class="faq-question-label faq-item-label">Q</div><div class="faq-question-content faq-item-content">ValueErrorとTypeErrorはどう使い分ければいいですか？</div></dt><dd class="faq-answer faq-item"><div class="faq-answer-label faq-item-label">A</div><div class="faq-answer-content faq-item-content">
<p>目安は「<strong>型は合っているか</strong>」です。</p>



<ul class="wp-block-list">
<li><code>TypeError</code>：引数の型そのものが想定と違う</li>



<li><code>ValueError</code>：型は正しいが、値の内容が不正</li>
</ul>



<p>たとえば、数値を期待している関数に文字列が渡された場合は <code>TypeError</code>、 数値だが範囲外（負の値など）の場合は <code>ValueError</code> が自然です。</p>
</div></dd></dl></div>



<div class="wp-block-cocoon-blocks-faq faq-wrap blank-box block-box not-nested-style cocoon-block-faq"><dl class="faq"><dt class="faq-question faq-item"><div class="faq-question-label faq-item-label">Q</div><div class="faq-question-content faq-item-content">例外メッセージは英語と日本語、どちらがよいですか？</div></dt><dd class="faq-answer faq-item"><div class="faq-answer-label faq-item-label">A</div><div class="faq-answer-content faq-item-content">
<p>結論から言うと、<strong>プロジェクトで統一されていればどちらでもOK</strong>です。</p>



<p>ただし、</p>



<ul class="wp-block-list">
<li>ライブラリ・フレームワーク → 英語</li>



<li>社内ツール・個人開発 → 日本語でも可</li>
</ul>



<p>という使い分けが一般的です。 重要なのは言語よりも、「具体的で再現可能な情報」が含まれていることです。</p>
</div></dd></dl></div>



<div class="wp-block-cocoon-blocks-faq faq-wrap blank-box block-box not-nested-style cocoon-block-faq"><dl class="faq"><dt class="faq-question faq-item"><div class="faq-question-label faq-item-label">Q</div><div class="faq-question-content faq-item-content">カスタム例外を作りすぎるのはアンチパターンですか？</div></dt><dd class="faq-answer faq-item"><div class="faq-answer-label faq-item-label">A</div><div class="faq-answer-content faq-item-content">
<p>はい、場合によってはアンチパターンになります。</p>



<p>「例外ごとに1クラス」を無条件で作ると、</p>



<ul class="wp-block-list">
<li>例外階層が把握しづらくなる</li>



<li>exceptの分岐が複雑になる</li>
</ul>



<p>といった問題が起きやすくなります。</p>



<p><strong>組み込み例外で意味が伝わるなら、それを使う</strong>。 <strong>ドメイン固有の意味がある場合だけ、カスタム例外を作る</strong>。 このバランスを意識するのが、長く保守できる設計につながります。</p>
</div></dd></dl></div>
]]></content:encoded>
					
					<wfw:commentRss>https://python.cbagames.jp/2025/12/22/python-exception-raise-best-practices/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
