2.2.1 最終化 (finalization) と解放

    destructor tp_dealloc;

型のインスタンスの参照カウントがゼロになり、 Python インタプリタがそれを潰して再利用したくなると、 この関数が呼ばれます。解放すべきメモリをその型が保持していたり、 それ以外にも実行すべき後処理がある場合は、それらをここに入れます。 オブジェクトそれ自体もここで解放される必要があります。 この関数の例は、以下のようなものです:

static void
newdatatype_dealloc(newdatatypeobject * obj)
{
    free(obj->obj_UnderlyingDatatypePtr);
    obj->ob_type->tp_free(obj);
}

解放用関数でひとつ重要なのは、処理待ちの例外にいっさい手をつけないことです。 なぜなら、解放用の関数は Python インタプリタがスタックを元の状態に戻すときに 呼ばれることが多いからです。そして (通常の関数からの復帰でなく) 例外のために スタックが巻き戻されるときは、すでに発生している例外から解放用関数を 守るものはありません。解放用の関数がおこなう動作が追加の Python のコードを 実行してしまうと、それらは例外が発生していることを検知するかもしれません。 これはインタプリタが誤解させるエラーを発生させることにつながります。 これを防ぐ正しい方法は、安全でない操作を実行する前に処理待ちの例外を 保存しておき、終わったらそれを元に戻すことです。これは PyErr_Fetch() および PyErr_Restore() 関数を使うことによって 可能になります:

static void
my_dealloc(PyObject *obj)
{
    MyObject *self = (MyObject *) obj;
    PyObject *cbresult;

    if (self->my_callback != NULL) {
        PyObject *err_type, *err_value, *err_traceback;
        int have_error = PyErr_Occurred() ? 1 : 0;

        if (have_error)
            PyErr_Fetch(&err_type, &err_value, &err_traceback);

        cbresult = PyObject_CallObject(self->my_callback, NULL);
        if (cbresult == NULL)
            PyErr_WriteUnraisable();
        else
            Py_DECREF(cbresult);

        if (have_error)
            PyErr_Restore(err_type, err_value, err_traceback);

        Py_DECREF(self->my_callback);
    }
    obj->ob_type->tp_free((PyObject*)self);
}

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。