4. 例外の取り扱い

この章で記述される関数は、あなたにPythonの例外を扱わせて、 そして例外を起こさせてくれる。Pythonの例外処理の基礎をいくつか 理解することが重要である。 それはいくぶんUnixのerrno変数のように働く: 起こった最後のエラーの(スレッドごとの)大域的な指示子がある。 たいていの関数は成功のときにこれを消さないが、 失敗のときにそれがエラーの原因を指すように設定する。 たいていの関数はまたエラーの指示子を返す。それは通常は、 関数がポインタを返すものとされているのであればNULL、 もしくは整数を返すのであれば-1である (例外: PyArg_Parse*()関数は成功には1を、 失敗には0を返す)。 呼び出したいくつかの関数が失敗したために、ある関数が失敗しなければ ならないときは、その関数は一般にエラーの指示子を設定しない。 それが呼び出した関数が既に設定しているからだ。

エラーの指示子は、 Python変数sys.exc_type, sys.exc_valuesys.exc_tracebackに対応する3つのPythonオブジェクトから 構成される。様々な方法でエラー指示子とやりとりするために API関数が存在する。それぞれのスレッドに対して独立したエラー 指示子がある。

void PyErr_Print ()
sys.stderrへ標準のトレースバックを表示して、エラー指示子を消す。 エラー指示子が設定されているときにだけこの関数を呼ぶこと (さもなければ致命的なエラーをもたらすだろう)。

PyObject* PyErr_Occurred ()
Return value: Borrowed reference.
エラー指示子が設定されているか検査する。もし設定されていれば、 例外型(type) (PyErr_Set*()関数の1つもしくはPyErr_Restore() への最後の呼び出しに対する第1引数)を返す。 もし設定されていなければ、NULLを返す。 あなたは戻り値への参照を所有しないので、それをPy_DECREF() する必要はない。 注意: 戻り値を特定の例外を比較しないように。代わりに 以下で示されるPyErr_ExceptionMatches()を使いなさい。 (クラスによる例外の場合、その例外はクラスの代わりにインスタンス かもしれないので、もしくは期待する例外のサブクラスかもしれないので、 比較は簡単に失敗し得る)。

int PyErr_ExceptionMatches (PyObject *exc)
"PyErr_GivenExceptionMatches(PyErr_Occurred(), exc)"と 同じである。これは例外が本当に設定されたときに呼ばれるだけで あるべきである。何も例外が起きていなければ、メモリアクセス 違反が起こるだろう。

int PyErr_GivenExceptionMatches (PyObject *given, PyObject *exc)
もしgivenの例外がexcの例外に合えば真を返す。 excがクラスオブジェクトであれば、これは givenがサブクラスのインスタンスであるときにもまた 真を返す。もし、excがタプルであれば、 タプル中の例外全てについて(そしてサブタプルのなかを再帰的に) 合うものを検索される。 もしgivenNULLであれば、メモリアクセス違反が起こるだろう。

void PyErr_NormalizeException (PyObject**exc, PyObject**val, PyObject**tb)
ある状況のもとでは、下記のPyErr_Fetch()によって 返された値は``正規化されていない''ことがあり得る。これは、 *excがクラスオブジェクトであるが、 *valがそれと同じクラスのインスタンスでないという 意味である。 そのような場合は、そのクラスをインスタンス化するためにこの関数を 使うことができる。もし値が既に正規化されていれば、何も起こらない。 遅延正規化は実行効率を向上させるために実装されている。

void PyErr_Clear ()
エラー指示子を取り除く。もしエラー指示子が設定されていなければ、 何も効果はない。

void PyErr_Fetch (PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)
エラー指示子をアドレスを渡された3個の変数に取り出す。 もしエラー指示子が設定されていなければ、3個の変数全てを NULLに設定する。もし指示子が設定されていれば、それは 取り除かれて、あなたは取り出したそれぞれのオブジェクトへの 参照を所有する。 型オブジェクトがNULLでないときでも、その値とトレースバック オブジェクトはNULLであるかもしれない。 注意: この関数は通常は例外を処理する必要があるコード、もしくは エラー指示子を一時的に保存して元に戻す必要のあるコードに 使用されるだけである。

void PyErr_Restore (PyObject *type, PyObject *value, PyObject *traceback)
3個のオブジェクトからエラー指示子を設定する。 もしエラー指示子が既に設定されていれば、初めにそれが取り除かれる。 もしオブジェクトがNULLであれば、エラー指示子は取り除かれる。 NULLのtypeとNULLでないvalueもしくはtracebackを渡さないこと。 例外の型(type)は文字列もしくはクラスであるべきである。 もしそれがクラスであれば、値(value)はそのクラスのインスタンスで あるべきである。無効な例外の型(type)や値(value)を渡してはならない。 (これらの規則を破ると後でささいな問題を引き起こすだろう)。 この呼び出しによって、それぞれのオブジェクトへの参照は奪われる。 つまり、あなたは呼び出しの前にそれぞれのオブジェクトへの参照を 所有していなければならなく、そして呼び出しの後はもはやあなたは これらの参照を所有していない (もしあなたがこれを理解していないのであれば、この関数を 使ってはならない。注意しておく)。 注:この関数は、通常は エラー指示子を一時的に保存して元に戻す必要のあるコードに 使用されるだけである。

void PyErr_SetString (PyObject *type, char *message)
これはエラー指示子を設定する最も普通の方法である。 第1引数は例外の型を指定する。それは普通は標準例外の1つ、例えば PyExc_RuntimeErrorである。その参照回数を増やす必要はない。 第2引数はエラーメッセージである。それは文字列オブジェクトに変換される。

void PyErr_SetObject (PyObject *type, PyObject *value)
この関数はPyErr_SetString()に似ているが、 例外の``値(value)''として任意のPythonオブジェクトを指定させてくれる。 そのオブジェクトの参照回数を増やす必要はない。

PyObject* PyErr_Format (PyObject *exception, const char *format, ...)
Return value: Always NULL.
この関数はprintf形式の書式文字列を使ってエラー指示子を設定する。 第1引数は例外の型を、第2引数は例外への書式文字列である。 後続のどの引数もC言語ライブラリのvsprintf()関数に よって出力へと変換される。 PyErr_Format()によって内部的に使われるバッファは 500バイトの長さである。呼び出し側はフォーマットされた出力が バッファをあふれないことを保証する責任がある。

void PyErr_SetNone (PyObject *type)
これは"PyErr_SetObject(type, Py_None)"を 手早く書くためのものである。

int PyErr_BadArgument ()
これは"PyErr_SetString(PyExc_TypeError, message)"を 手早く書くためのものである。ここでmessageは 組み込みの操作が不正な引数とともに起動されたことを示す。 たいていは内部で使用するためである。

PyObject* PyErr_NoMemory ()
Return value: Always NULL.
これは"PyErr_SetNone(PyExc_MemoryError)"を 手早く書くためのものである。 この関数は、メモリを使い果したときに、オブジェクトを割り当てる 関数が"return PyErr_NoMemory();"と書くことができるよう NULLを返す。

PyObject* PyErr_SetFromErrno (PyObject *type)
Return value: Always NULL.
これはCライブラリ関数の関数がエラーを返し、C言語の変数errnoを 設定したときに例外を起こすための、便宜的な関数である。 その関数は、1番目のアイテムが整数のerrnoの値で、 2番目のアイテムが (strerror()から取得した) 対応するエラーメッセージであるタプルオブジェクトを構築して、 "PyErr_SetObject(type, object)"を呼び出す。 Unixでは、errnoの値が 中断されたシステムコールを意味するEINTRであるとき、 この関数はPyErr_CheckSignals()を呼び出す。 そして、もしその関数がエラー指示子を設定したのであれば、 エラー指示子をそれに設定したままにしておく。 この関数は常にNULLを返すので、システムコール周りのラッパー 関数は、システムコールがエラーを返したときに、 "return PyErr_SetFromErrno();"と書くことができる。

void PyErr_BadInternalCall ()
これは"PyErr_SetString(PyExc_TypeError, message)"を 手早く書くためのものである。ここで、messageは 内部操作(例えばPython/C API関数など)が不正な引数とともに 起動されたことを示す。 たいていは内部で使用するためである。

int PyErr_CheckSignals ()
この関数はPythonのシグナル処理と相互作用する。 それはプロセスにシグナルが送られたか検査して、もしそうであれば 対応するシグナルハンドラを起動する。 もしsignalモジュールが 利用可能であれば、この関数はPythonで書かれたシグナルハンドラを起動する ことができる。全ての場合で、SIGINTに対する デフォルトの結果は、 KeyboardInterrupt例外を起こすことである。 もし例外が起こされたら、エラー指示子が設定されて、その関数は1を返す。 そうでなければ関数は0を返す。もしエラー指示子が以前に設定された場合、 それは取り消されるかもしれないし、取り消されないかもしれない。

void PyErr_SetInterrupt ()
この関数は廃止予定である。 これはSIGINTシグナルが到着した影響を シミュレートする -- 次にPyErr_CheckSignals()が呼び出されたときに、 KeyboardInterruptが起こされる。 この関数はインタープリタのロックを保持せずに呼び出されてもよい。

PyObject* PyErr_NewException (char *name, PyObject *base, PyObject *dict)
Return value: New reference.
このユーティリティ関数は新しい例外オブジェクトを作って返す。 name引数は、module.classの形式のC言語文字列である 新しい例外の名前でなければならない。 basedict引数は通常はNULLである。 通常はこれは、組み込み名がException (C言語ではPyExc_Exceptionとして利用できる)である、 全ての例外のルートから派生されたクラスオブジェクトを作成する。 この場合、新しいクラスの__module__属性は name引数の始めの部分(最後のドットまで)に設定される。 そして、クラス名はその最後の部分(最後のドット以降)に設定される。 base引数は、他の基底クラスを指定するために使うことができる。 dict引数はクラスの変数とメソッドの辞書を指定するために 使うことができる。


Subsections