目次

前のトピックへ

参照カウント

次のトピックへ

ユーティリティ関数

このページ

例外処理

この章で説明する関数を使うと、Pythonの例外の処理や送出ができるようになります。Pythonの例外処理の基本をいくらか理解することが大切です。 例外はUnix errno 変数にやや似た機能を果たします: 発生した 中で最も新しいエラーの(スレッド毎の)グローバルなインジケータがあります。実行に成功した場合にはほとんどの関数がこれをクリアしませんが、失敗したときには エラーの原因を示すために設定します。ほとんどの関数はエラーインジケータも返し、通常は関数がポインタを返すことになっている場合は NULL であり、 関数が整数を返す場合は -1 です。(例外: PyArg_*() 関数は 実行に成功したときに 1 を返し、失敗したときに 0 を返します).

ある関数が呼び出した関数がいくつか失敗したために、その関数が失敗しなければならないとき、一般的にエラーインジケータを設定しません。呼び出した関数が すでに設定しています。エラーを処理して例外をクリアするか、あるいは (オブジェクト参照またはメモリ割り当てのような)それが持つどんなリソースも 取り除いた後に戻るかのどちらか一方を行う責任があります。エラーを処理する準備をしていなければ、普通に続けるべきでは ありません 。エラーのために 戻る場合は、エラーが設定されていると呼び出し元に知らせることが大切です。エラーが処理されていない場合または丁寧に伝えられている場合には、 Python/C APIのさらなる呼び出しは意図した通りには動かない可能性があり、不可解な形で失敗するかもしれません。

エラーインジケータは Python変数 sys.exc_type, sys.exc_value および sys.exc_traceback に対応する三つのPythonオブジェクトからからなります。 いろいろな方法でエラーインジケータとやりとりするためにAPI関数が存在します。各スレッドに別々のエラーインジケータがあります。

void PyErr_PrintEx(int set_sys_last_vars)

sys.stderr へ標準トレースバックをプリントし、エラーインジケータをクリアします。エラーインジケータが設定されているときにだけ、この関数を 呼び出してください。(それ以外の場合、致命的なエラーを引き起こすでしょう!)

set_sys_last_vars が非ゼロであれば、 sys.last_type, sys.last_value, sys.last_traceback 変数が、表示される例外のタイプ、値、トレースバックそれぞれに 反映されます。

void PyErr_Print()

PyErr_PrintEx(1) のエイリアス.

PyObject* PyErr_Occurred()
Return value: Borrowed reference.

エラーインジケータが設定されているかテストします。設定されている場合は、例外の (PyErr_Set*() 関数の一つあるいは PyErr_Restore() への最も新しい呼び出しに対する第一引数)を返します。 設定されていない場合は 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 がタプルならば、タプル内(と再帰的にサブタプル内)のすべての例外が一致するか調べられます。

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)

エラーインジケータをアドレスを渡す三つの変数の中へ取り出します。エラーインジケータが設定されていない場合は、三つすべての変数を NULL に 設定します。エラーインジケータが設定されている場合はクリアされ、あなたは取り出されたそれぞれのオブジェクトへの参照を持つことになります。 型オブジェクトが NULL でないときでさえ、その値とトレースバックオブジェクトは NULL かもしれません。

ノート

通常、この関数は例外を扱う必要のあるコードあるいはエラーインジケータを一時的に保存して元に戻す必要のあるコードによってのみ使用されます。

void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)

三つのオブジェクトからエラーインジケータを設定します。エラーインジケータがすでに設定されている場合は、最初にクリアされます。オブジェクトが NULL ならば、 エラーインジケータがクリアされます。 NULL のtypeと非 NULL のvalueあるいは tracebackを渡してはいけません。例外の型(type)はクラスであるべきです。無効な例外の型(type)あるいは値(value)を渡してはいけません。 (これらの規則を破ると後で気付きにくい問題の原因となるでしょう。) この呼び出しはそれぞれのオブジェクトへの参照を取り除きます: あなたは 呼び出しの前にそれぞれのオブジェクトへの参照を持たなければならないのであり、また呼び出しの後にはもはやこれらの参照を持っていません。 (これを理解していない場合は、この関数を使ってはいけません。注意しておきます。)

ノート

通常この関数はエラーインジケータを一時的に保存し元に戻す必要のあるコードによってのみに使われます。現在の例外状態を保存するためには PyErr_Fetch() を使ってください。

void PyErr_SetString(PyObject *type, const char *message)

これはエラーインジケータを設定するための最も一般的な方法です。第一引数は 例外の型を指定します。通常は標準例外の一つ、例えば PyExc_RuntimeError です。 その参照カウントを増加させる必要はありません。第二引数はエラーメッセージで、文字列オブジェクトへ変換されます。

void PyErr_SetObject(PyObject *type, PyObject *value)

この関数は PyErr_SetString() に似ていますが、 例外の”値(value)”として任意のPythonオブジェクトを指定することができます。

PyObject* PyErr_Format(PyObject *exception, const char *format, ...)
Return value: Always NULL.

この関数はエラーインジケータを設定し NULL を返します。 exception はPython例外(インスタンスではなくクラス)であるべきです。 format は文字列であるべきであり、 printf() に似た 書式化コードを含んでいます。書式化コードの前の 幅.精度(width.precision) は解析されますが、幅の部分は無視されます。

書式文字 コメント
%% n/a リテラルの % 文字。
%c int 一文字. Cのintで表現される。
%d int printf("%d") と完全に同じ。
%u unsigned int printf("%u") と完全に同じ。
%ld long printf("%ld") と完全に同じ。
%lu unsigned long printf("%lu") と完全に同じ。
%zd Py_ssize_t printf("%zd") と完全に同じ。
%zu size_t printf("%zu") と完全に同じ.
%i int printf("%i") と完全に同じ。
%x int printf("%x") と完全に同じ。
%s char* NULL終端の C の文字配列。
%p void* C ポインタの16進表現。 プラットフォームのprintfによらず、必ずリテラル 0x が頭につくことが保証される という以外、 printf("%p") とほぼ同じ。

認識できない書式化文字があると書式化文字列の残りすべてがそのまま結果の文字列へコピーされ、余分の引数はどれも捨てられます。

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) を省略したもので、 NULL を返します。したがって、メモリ不足になったとき、 オブジェクト割り当て関数は return PyErr_NoMemory(); と書くことができます。

PyObject* PyErr_SetFromErrno(PyObject *type)
Return value: Always NULL.

Cライブラリ関数がエラーを返してC変数 errno を設定したときに、これは例外を発生させるために便利な関数です。第一要素が 整数 errno 値で、第二要素が (strerror() から得られる)対応する エラーメッセージであるタプルオブジェクトを構成します。それから、 PyErr_SetObject(type, object) を呼び出します。 Unixでは、 errno 値が EINTR であるとき、すなわち割り込まれたシステムコールを表しているとき、これは PyErr_CheckSignals() を呼び出し、それがエラーインジケータを 設定した場合は設定されたままにしておきます。関数は常に NULL を返します。したがって、システムコールがエラーを返したとき、システムコールの ラッパー関数は return PyErr_SetFromErrno(type); と書くことができます。

PyObject* PyErr_SetFromErrnoWithFilename(PyObject *type, const char *filename)
Return value: Always NULL.

PyErr_SetFromErrno() に似ていて、 filenameNULL でない場合に、 それが type のコンストラクタに第三引数として渡されるというふるまいが追加 されています。 IOErrorOSError のような例外の場合では、 これが例外インスタンスの filename 属性を定義するために使われます。

PyObject* PyErr_SetFromWindowsErr(int ierr)
Return value: Always NULL.

これは WindowsError を発生させるために便利な関数です。 0ierr とともに呼び出された場合、 GetLastError() が 返すエラーコードが代りに使われます。 ierr あるいは GetLastError() によって与えられるエラーコードのWindows用の説明を 取り出すために、Win32関数 FormatMessage() を呼び出します。それから、 第一要素が ierr 値で第二要素が(FormatMessage() から得られる) 対応するエラーメッセージであるタプルオブジェクトを構成します。そして、 PyErr_SetObject(PyExc_WindowsError, object) を呼び出します。この関数は常に NULL を返します。利用可能範囲: Windows。

PyObject* PyErr_SetExcFromWindowsErr(PyObject *type, int ierr)
Return value: Always NULL.

PyErr_SetFromWindowsErr() に似ていて、送出する例外の型を指定する引数が追加されています。利用可能範囲: Windows。

バージョン 2.3 で追加.

PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename)
Return value: Always NULL.

PyErr_SetFromWindowsErr() に似ていて、 filenameNULL でない場合には WindowsError のコンストラクタへ第三引数として渡されるという振る舞いが追加されています。利用可能範囲: Windows。

PyObject* PyErr_SetExcFromWindowsErrWithFilename(PyObject *type, int ierr, char *filename)
Return value: Always NULL.

PyErr_SetFromWindowsErrWithFilename() に似ていて、発生させる例外の型を指定する引数が追加されています。 利用可能範囲: Windows。

バージョン 2.3 で追加.

void PyErr_BadInternalCall()

PyErr_SetString(PyExc_TypeError, message) を省略したものです。 ここで message は内部操作(例えば、Python/C API関数)が不正な引数と ともに呼び出されたということを示しています。主に内部で使用するためのものです。

int PyErr_WarnEx(PyObject *category, char *message, int stacklevel)

警告メッセージを出します。 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_WarningPyExc_Exception のサブクラスです。 その他の警告カテゴリは PyExc_Warning のサブクラスです。

警告をコントロールするための情報については、 warnings モジュールのドキュメンテーションとコマンドライン・ドキュメンテーションの -W オプションを参照してください。警告コントロールのためのC APIはありません。

int PyErr_Warn(PyObject *category, char *message)

警告メッセージを出します。 category 引数は警告カテゴリ(以下を参照) かまたは NULL で、 message 引数はメッセージ文字列です。警告は 、 PyErr_WarnEx()stacklevel に 1 を指定した時と同じく、 PyErr_Warn() を呼び出した関数から発行されます。

非推奨; PyErr_WarnEx() を使って下さい。

int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry)

すべての警告の属性を明示的に制御した警告メッセージを出します。 これはPython関数 warnings.warn_explicit() の直接的なラッパで、 さらに情報を得るにはそちらを参照してください。そこに説明されているデフォルトの 効果を得るために、 moduleregistry 引数は NULL に設定することができます。

int PyErr_WarnPy3k(char *message, int stacklevel)

Issue a DeprecationWarning with the given message and stacklevel if the Py_Py3kWarningFlag flag is enabled. Py_Py3kWarningFlag フラグが有効な場合、 与えられた messagestacklevel に応じて DeprecationWarning を発生させます。

バージョン 2.6 で追加.

int PyErr_CheckSignals()

この関数はPythonのシグナル処理とやりとりすることができます。シグナルがそのプロセスへ送られたかどうかチェックし、そうならば対応する シグナルハンドラを呼び出します。 signal モジュールがサポートされている場合は、 これはPythonで書かれたシグナルハンドラを呼び出せます。すべての場合で、 SIGINT のデフォルトの効果は KeyboardInterrupt 例外を発生させることです。例外が発生した場合、エラーインジケータが設定され、関数は -1 を返します。 そうでなければ、関数は 0 を返します。エラーインジケータが以前に設定されている場合は、それがクリアされるかどうかわからない。

void PyErr_SetInterrupt()

この関数は廃止されています。 SIGINT シグナルが到達した影響をシミュレートします — 次に PyErr_CheckSignals() が呼ばれるとき、 KeyboardInterrupt は送出されるでしょう。インタプリタロックを保持することなく呼び出すことができます。

int PySignal_SetWakeupFd(int fd)

このユーティリティ関数は、シグナルを受信したときに '\0' バイトを書き込む ファイルディスクリプタを指定します。戻り値は、それまで設定されていたファイル ディスクリプタです。 -1 はこの機能を無効にします。これは初期状態です。 これは Python の signal.set_wakeup_fd() と同じものですが、 エラーチェックを行ないません。 fd は有効なファイルディスクリプタであるべきです。 この関数の呼び出しはメインスレッドのみから行われるべきです。

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 引数はクラス変数とメソッドの辞書を指定するために使えます。

void PyErr_WriteUnraisable(PyObject *obj)

例外が設定されているがインタプリタが実際に例外を発生させることができないときに、 このユーティリティ関数は警告メッセージを sys.stderr へプリントします。 例えば、例外が __del__() メソッドで発生したときに使われます。

発生させられない例外が生じたコンテキストを特定するための一つの引数 obj とともに 関数が呼び出されます。 obj のreprが警告メッセージにプリントされるでしょう。

標準例外

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  

注記:

  1. これは別の標準例外のためのベースクラスです。

  2. これは weakref.ReferenceError と同じです。

  3. Windowsでのみ定義されています。プリプロセッサマクロ MS_WINDOWS が定義されているかテストすることで、 これを使うコードを保護してください。

  4. バージョン 2.5 で追加.

文字列例外の廃止

Pythonへ組み込まれるすべての例外あるいは標準ライブラリに提供されている例外は、 BaseException から導出されています。

インタプリタで既存のコードが変更なしで動作するように、文字列例外は今でもサポートされています。しかし、これも将来のリリースで変更されるでしょう。