この章で説明する関数を使うと、 Python の例外の処理や送出ができるようになります。 Python の例外処理の基本をいくらか理解することが大切です。例外は Unix errno 変数にやや似た機能を果たします: 発生した中で最も新しいエラーの (スレッド毎の) グローバルなインジケータがあります。実行に成功した場合にはほとんどの関数がこれをクリアしませんが、失敗したときにはエラーの原因を示すために設定します。ほとんどの関数はエラーインジケータも返し、通常は関数がポインタを返すことになっている場合は NULL であり、関数が整数を返す場合は -1 です。(例外: PyArg_*() 関数は実行に成功したときに 1 を返し、失敗したときに 0 を返します).
ある関数が呼び出した関数がいくつか失敗したために、その関数が失敗しなければならないとき、一般的にエラーインジケータを設定しません。呼び出した関数がすでに設定しています。エラーを処理して例外をクリアするか、あるいは (オブジェクト参照またはメモリ割り当てのような)それが持つどんなリソースも取り除いた後に戻るかのどちらか一方を行う責任があります。エラーを処理する準備をしていなければ、普通に続けるべきでは ありません 。エラーのために戻る場合は、エラーが設定されていると呼び出し元に知らせることが大切です。エラーが処理されていない場合または丁寧に伝えられている場合には、 Python/C APIのさらなる呼び出しは意図した通りには動かない可能性があり、不可解な形で失敗するかもしれません。
エラーインジケータは Python変数 sys.exc_type, sys.exc_value および sys.exc_traceback に対応する三つのPythonオブジェクトからからなります。いろいろな方法でエラーインジケータとやりとりするためにAPI関数が存在します。各スレッドに別々のエラーインジケータがあります。
sys.stderr へ標準トレースバックをプリントし、エラーインジケータをクリアします。エラーインジケータが設定されているときにだけ、この関数を呼び出してください。(それ以外の場合、致命的なエラーを引き起こすでしょう!)
set_sys_last_vars が非ゼロであれば、 sys.last_type, sys.last_value, sys.last_traceback 変数が、表示される例外のタイプ、値、トレースバックそれぞれに反映されます。
PyErr_PrintEx(1) のエイリアス.
エラーインジケータが設定されているかテストします。設定されている場合は、例外の 型 (PyErr_Set*() 関数の一つあるいは PyErr_Restore() への最も新しい呼び出しに対する第一引数)を返します。設定されていない場合は NULL を返します。あなたは戻り値への参照を持っていませんので、それに Py_DECREF() する必要はありません。
ノート
戻り値を特定の例外と比較しないでください。その代わり、下に示す PyErr_ExceptionMatches() を使ってください。(比較は簡単に失敗するでしょう。なぜなら、例外はクラスではなくインスタンスかもしれないし、あるいは、クラス例外の場合は期待される例外のサブクラスかもしれないからです。)
PyErr_GivenExceptionMatches(PyErr_Occurred(), exc) と同じ。例外が実際に設定されたときにだけ、これを呼び出だすべきです。例外が発生していないならば、メモリアクセス違反が起きるでしょう。
given 例外が exc の例外と一致するなら真を返します。これは exc がクラスオブジェクトである場合も真を返します。これは given がサブクラスのインスタンスであるときも真を返します。 exc がタプルならば、タプル内(と再帰的にサブタプル内)のすべての例外が一致するか調べられます。
ある状況では、以下の PyErr_Fetch() が返す値は “正規化されていない” 可能性があります。つまり、 *exc はクラスオブジェクトだが *val は同じクラスのインスタンスではないという意味です。この関数はそのような場合にそのクラスをインスタンス化するために使われます。その値がすでに正規化されている場合は何も起きません。遅延正規化はパフォーマンスを改善するために実装されています。
エラーインジケータをクリアします。エラーインジケータが設定されていないならば、効果はありません。
エラーインジケータをアドレスを渡す三つの変数の中へ取り出します。エラーインジケータが設定されていない場合は、三つすべての変数を NULL に設定します。エラーインジケータが設定されている場合はクリアされ、あなたは取り出されたそれぞれのオブジェクトへの参照を持つことになります。型オブジェクトが NULL でないときでさえ、その値とトレースバックオブジェクトは NULL かもしれません。
ノート
通常、この関数は例外を扱う必要のあるコードあるいはエラーインジケータを一時的に保存して元に戻す必要のあるコードによってのみ使用されます。
三つのオブジェクトからエラーインジケータを設定します。エラーインジケータがすでに設定されている場合は、最初にクリアされます。オブジェクトが NULL ならば、エラーインジケータがクリアされます。 NULL のtypeと非 NULL のvalueあるいは tracebackを渡してはいけません。例外の型(type)はクラスであるべきです。無効な例外の型(type)あるいは値(value)を渡してはいけません。 (これらの規則を破ると後で気付きにくい問題の原因となるでしょう。) この呼び出しはそれぞれのオブジェクトへの参照を取り除きます: あなたは呼び出しの前にそれぞれのオブジェクトへの参照を持たなければならないのであり、また呼び出しの後にはもはやこれらの参照を持っていません。 (これを理解していない場合は、この関数を使ってはいけません。注意しておきます。)
ノート
通常この関数はエラーインジケータを一時的に保存し元に戻す必要のあるコードによってのみに使われます。現在の例外状態を保存するためには PyErr_Fetch() を使ってください。
これはエラーインジケータを設定するための最も一般的な方法です。第一引数は例外の型を指定します。通常は標準例外の一つ、例えば PyExc_RuntimeError です。その参照カウントを増加させる必要はありません。第二引数はエラーメッセージで、文字列オブジェクトへ変換されます。
この関数は PyErr_SetString() に似ていますが、例外の”値(value)”として任意のPythonオブジェクトを指定することができます。
この関数はエラーインジケータを設定し NULL を返します。 exception はPython例外クラスであるべきです。 format と以降の引数はエラーメッセージを作るためのもので, PyString_FromFormat() の引数と同じ意味を持っています。
これは PyErr_SetString(PyExc_TypeError, message) を省略したもので、ここで message は組み込み操作が不正な引数で呼び出されたということを表しています。主に内部で使用するためのものです。
これは PyErr_SetNone(PyExc_MemoryError) を省略したもので、 NULL を返します。したがって、メモリ不足になったとき、オブジェクト割り当て関数は return PyErr_NoMemory(); と書くことができます。
Cライブラリ関数がエラーを返してC変数 errno を設定したときに、これは例外を発生させるために便利な関数です。第一要素が整数 errno 値で、第二要素が (strerror() から得られる)対応するエラーメッセージであるタプルオブジェクトを構成します。それから、 PyErr_SetObject(type, object) を呼び出します。 Unixでは、 errno 値が EINTR であるとき、すなわち割り込まれたシステムコールを表しているとき、これは PyErr_CheckSignals() を呼び出し、それがエラーインジケータを設定した場合は設定されたままにしておきます。関数は常に NULL を返します。したがって、システムコールがエラーを返したとき、システムコールのラッパー関数は return PyErr_SetFromErrno(type); と書くことができます。
PyErr_SetFromErrno() に似ていて、 filename が NULL でない場合に、それが type のコンストラクタに第三引数として渡されるというふるまいが追加されています。 IOError と OSError のような例外の場合では、これが例外インスタンスの filename 属性を定義するために使われます。
これは WindowsError を発生させるために便利な関数です。 0 の ierr とともに呼び出された場合、 GetLastError() が返すエラーコードが代りに使われます。 ierr あるいは GetLastError() によって与えられるエラーコードのWindows用の説明を取り出すために、Win32関数 FormatMessage() を呼び出します。それから、第一要素が ierr 値で第二要素が(FormatMessage() から得られる) 対応するエラーメッセージであるタプルオブジェクトを構成します。そして、 PyErr_SetObject(PyExc_WindowsError, object) を呼び出します。この関数は常に NULL を返します。利用可能範囲: Windows。
PyErr_SetFromWindowsErr() に似ていて、送出する例外の型を指定する引数が追加されています。利用可能範囲: Windows。
バージョン 2.3 で追加.
PyErr_SetFromWindowsErr() に似ていて、 filename が NULL でない場合には WindowsError のコンストラクタへ第三引数として渡されるという振る舞いが追加されています。利用可能範囲: Windows。
PyErr_SetFromWindowsErrWithFilename() に似ていて、発生させる例外の型を指定する引数が追加されています。利用可能範囲: Windows。
バージョン 2.3 で追加.
PyErr_SetString(PyExc_SystemError, message) を省略したものです。ここで message は内部操作(例えば、Python/C API関数)が不正な引数とともに呼び出されたということを示しています。主に内部で使用するためのものです。
警告メッセージを出します。 category 引数は警告カテゴリ(以下を参照) かまたは NULL で、 message 引数はメッセージ文字列です。 stacklevel はフレームの数を示す正の整数です; 警告はそのスタックフレームの中の実行している行から発行されます。 stacklevel が1だと、 PyErr_WarnEx() が、2だとその上の関数が、Warningの発行元になります。
この関数は通常警告メッセージを sys.stderr へプリントします。けれども、ユーザが警告をエラーへ変更するように指定することも可能です。そのような場合には、これは例外を発生させます。警告機構がもつ問題のためにその関数が例外を発生させるということも可能です。(実装ではその厄介な仕事を行うために warnings モジュールをインポートします)。例外が発生させられなければ、戻り値は 0 です。あるいは、例外が発生させられると -1 です。(警告メッセージが実際にプリントされるかどうかを決定することはできず、また何がその例外の原因なのかを決定することもできない。これは意図的なものです。)例外が発生した場合、呼び出し元は通常の例外処理を行います(例えば、 Py_DECREF() は参照を持っており、エラー値を返します)。
警告カテゴリは Warning のサブクラスでなければならない。デフォルト警告カテゴリは RuntimeWarning です。標準Python警告カテゴリは PyExc_ にPython例外名が続く名前のグローバル変数を用いて変更できます。これらは型 PyObject* を持ち、すべてクラスオブジェクトです。それらの名前は PyExc_Warning, PyExc_UserWarning, PyExc_UnicodeWarning, PyExc_DeprecationWarning, PyExc_SyntaxWarning, PyExc_RuntimeWarning, PyExc_FutureWarning です。 PyExc_Warning は PyExc_Exception のサブクラスです。その他の警告カテゴリは PyExc_Warning のサブクラスです。
警告をコントロールするための情報については、 warnings モジュールのドキュメンテーションとコマンドライン・ドキュメンテーションの -W オプションを参照してください。警告コントロールのためのC APIはありません。
警告メッセージを出します。 category 引数は警告カテゴリ(以下を参照) かまたは NULL で、 message 引数はメッセージ文字列です。警告は、 PyErr_WarnEx() を stacklevel に 1 を指定した時と同じく、 PyErr_Warn() を呼び出した関数から発行されます。
非推奨; PyErr_WarnEx() を使って下さい。
すべての警告の属性を明示的に制御した警告メッセージを出します。これはPython関数 warnings.warn_explicit() の直接的なラッパで、さらに情報を得るにはそちらを参照してください。そこに説明されているデフォルトの効果を得るために、 module と registry 引数は NULL に設定することができます。
Issue a DeprecationWarning with the given message and stacklevel if the Py_Py3kWarningFlag flag is enabled. Py_Py3kWarningFlag フラグが有効な場合、与えられた message と stacklevel に応じて DeprecationWarning を発生させます。
バージョン 2.6 で追加.
この関数はPythonのシグナル処理とやりとりすることができます。シグナルがそのプロセスへ送られたかどうかチェックし、そうならば対応するシグナルハンドラを呼び出します。 signal モジュールがサポートされている場合は、これはPythonで書かれたシグナルハンドラを呼び出せます。すべての場合で、 SIGINT のデフォルトの効果は KeyboardInterrupt 例外を発生させることです。例外が発生した場合、エラーインジケータが設定され、関数は -1 を返します。そうでなければ、関数は 0 を返します。エラーインジケータが以前に設定されている場合は、それがクリアされるかどうかわからない。
この関数は廃止されています。 SIGINT シグナルが到達した影響をシミュレートします — 次に PyErr_CheckSignals() が呼ばれるとき、 KeyboardInterrupt は送出されるでしょう。インタプリタロックを保持することなく呼び出すことができます。
このユーティリティ関数は、シグナルを受信したときに '\0' バイトを書き込むファイルディスクリプタを指定します。戻り値は、それまで設定されていたファイルディスクリプタです。 -1 はこの機能を無効にします。これは初期状態です。これは Python の signal.set_wakeup_fd() と同じものですが、エラーチェックを行ないません。 fd は有効なファイルディスクリプタであるべきです。この関数の呼び出しはメインスレッドのみから行われるべきです。
バージョン 2.6 で追加.
このユーティリティ関数は新しい例外オブジェクトを作成して返します。 name 引数は新しい例外の名前、 module.class 形式の C文字列でなければならない。 base と dict 引数は通常 NULL です。これはすべての例外のためのルート、組み込み名 Exception (Cでは PyExc_Exception としてアクセス可能)をルートとして派生したクラスオブジェクトを作成します。
新しいクラスの __module__ 属性は name 引数の前半部分(最後のドットまで)に設定され、クラス名は後半部分(最後のドットの後)に設定されます。 base 引数は代わりのベースクラスを指定するために使えます; 一つのクラスでも、クラスのタプルでも構いません。 dict 引数はクラス変数とメソッドの辞書を指定するために使えます。
PyErr_NewException() とほぼ同じですが、新しい例外クラスに簡単に docstring を設定できます。 doc が NULL で無い場合、それが例外クラスの docstring になります。
バージョン 2.7 で追加.
例外が設定されているがインタプリタが実際に例外を発生させることができないときに、このユーティリティ関数は警告メッセージを sys.stderr へプリントします。例えば、例外が __del__() メソッドで発生したときに使われます。
発生させられない例外が生じたコンテキストを特定するための一つの引数 obj とともに関数が呼び出されます。 obj のreprが警告メッセージにプリントされるでしょう。
以下の関数は C言語から Unicode 例外を作ったり修正したりするために利用します。
encoding, object, length, start, end, reason 属性をもった UnicodeDecodeError オブジェクトを作成します。
encoding, object, length, start, end, reason 属性を持った UnicodeEncodeError オブジェクトを作成します。
object, length, start, end, reason 属性を持った UnicodeTranslateError オブジェクトを作成します。
与えられた例外オブジェクトの encoding 属性を返します。
与えられた例外オブジェクトの object 属性を返します。
渡された例外オブジェクトから start 属性を取得して *start に格納します。 start は NULL であってはなりません。成功したら 0 を、失敗したら -1 を返します。
渡された例外オブジェクトの start 属性を start に設定します。成功したら 0 を、失敗したら -1 を返します。
渡された例外オブジェクトから end 属性を取得して *end に格納します。 end は NULL であってはなりません。成功したら 0 を、失敗したら -1 を返します。
渡された例外オブジェクトの end 属性を end に設定します。成功したら 0 を、失敗したら -1 を返します。
これら2つの関数は C レベルの再帰呼び出しを安全に実行する方法を、コアモジュールにも拡張モジュールにも提供します。再帰を使ったコードが必ずしも Python コードを実行するわけではない場合 (Python コードは再帰の深さを自動的に追跡します)、これらの関数が必要となります。
C レベルの再帰呼び出しをしようとしているところに印を付けます。
USE_STACKCHECK が定義されている場合、 OS のスタックがオーバーフローがしたかどうかを PyOS_CheckStack() を使ってチェックします。もしオーバーフローしているなら、 MemoryError をセットしゼロでない値を返します。
次にこの関数は再帰の上限に達していないかをチェックします。上限に達している場合、 RuntimeError をセットしゼロでない値を返します。そうでない場合はゼロを返します。
再帰の深さの上限に達して送出される RuntimeError のメッセージに連結できるよう where は " in instance check" のような文字列にしてください。
Py_EnterRecursiveCall() を終了させます。 Py_EnterRecursiveCall() の 成功した 呼び出しに対して必ず 1 回呼び出さなければなりません。
PyExc_ の後ろにPythonの例外名が続く名前をもつグローバル変数として、すべての標準Python例外が利用可能です。これらは型 PyObject* を持ち、すべてクラスオブジェクトです。完璧を期するために、すべての変数を以下に列挙します:
C名 | Python名 | 注記 |
---|---|---|
PyExc_BaseException | BaseException | (1), (4) |
PyExc_Exception | Exception | (1) |
PyExc_StandardError | StandardError | (1) |
PyExc_ArithmeticError | ArithmeticError | (1) |
PyExc_LookupError | LookupError | (1) |
PyExc_AssertionError | AssertionError | |
PyExc_AttributeError | AttributeError | |
PyExc_EOFError | EOFError | |
PyExc_EnvironmentError | EnvironmentError | (1) |
PyExc_FloatingPointError | FloatingPointError | |
PyExc_IOError | IOError | |
PyExc_ImportError | ImportError | |
PyExc_IndexError | IndexError | |
PyExc_KeyError | KeyError | |
PyExc_KeyboardInterrupt | KeyboardInterrupt | |
PyExc_MemoryError | MemoryError | |
PyExc_NameError | NameError | |
PyExc_NotImplementedError | NotImplementedError | |
PyExc_OSError | OSError | |
PyExc_OverflowError | OverflowError | |
PyExc_ReferenceError | ReferenceError | (2) |
PyExc_RuntimeError | RuntimeError | |
PyExc_SyntaxError | SyntaxError | |
PyExc_SystemError | SystemError | |
PyExc_SystemExit | SystemExit | |
PyExc_TypeError | TypeError | |
PyExc_ValueError | ValueError | |
PyExc_WindowsError | WindowsError | (3) |
PyExc_ZeroDivisionError | ZeroDivisionError |
注記:
これは別の標準例外のためのベースクラスです。
これは weakref.ReferenceError と同じです。
Windowsでのみ定義されています。プリプロセッサマクロ MS_WINDOWS が定義されているかテストすることで、これを使うコードを保護してください。
バージョン 2.5 で追加.
バージョン 2.6 で変更: All exceptions to be raised or caught must be derived from BaseException. Trying to raise a string exception now raises TypeError. 発生したりキャッチされる全ての例外は BaseException を継承しなければなりません。 文字列例外を発生させようとすると TypeError が発生されます。