Класс пользовательских исключений Boost.Python - PullRequest
13 голосов
/ 08 марта 2012

Я реализую модуль расширения Python, используя Boost.Python.Модуль должен определять свои собственные классы исключений, которые наследуют Exception.Как мне это сделать?

Ответы [ 2 ]

15 голосов
/ 13 марта 2012

Следующая функция создает новый класс исключений Python и добавляет его в текущую область. Если он вызывается в функции инициализации модуля, то он добавляется в модуль.

Первый аргумент - это имя нового класса исключений. Второй аргумент - это объект типа для базового класса нового класса исключений; по умолчанию это тип объекта Exception. Возвращаемое значение - это объект типа для нового класса исключений.

PyObject* createExceptionClass(const char* name, PyObject* baseTypeObj = PyExc_Exception)
{
    using std::string;
    namespace bp = boost::python;

    string scopeName = bp::extract<string>(bp::scope().attr("__name__"));
    string qualifiedName0 = scopeName + "." + name;
    char* qualifiedName1 = const_cast<char*>(qualifiedName0.c_str());

    PyObject* typeObj = PyErr_NewException(qualifiedName1, baseTypeObj, 0);
    if(!typeObj) bp::throw_error_already_set();
    bp::scope().attr(name) = bp::handle<>(bp::borrowed(typeObj));
    return typeObj;
}

Используйте функцию следующим образом:

Вызвать функцию в функции инициализации модуля и сохранить возвращаемое значение в глобальной переменной:

PyObject* myExceptionTypeObj = 0;

BOOST_PYTHON_MODULE(MyModule)
{
    ...
    myExceptionTypeObj = createExceptionClass("MyException");
    ...
}

Повышение исключения типа MyModule.MyException:

PyErr_SetString(myExceptionTypeObj, "Oh my!")
0 голосов
/ 24 апреля 2015

@ Кенни:

Если вы ссылаетесь на

PyErr_SetString(myExceptionTypeObj, "Oh my!")

Я бы не рассматривал это как "копирование строки в глобальный объект". Вместо этого он устанавливает индикатор внутренней ошибки Python, чтобы интерпретатор вызывал экземпляр myExceptionTypeObj при следующей проверке индикатора ошибки.

Обработка исключений в Python работает с индикатором глобальной ошибки (для потока Python), и это обычный способ вызвать исключение через API C API.

Я полагаю, что вы в безопасности, если в этот момент вы держите GIL, и это вызовет исключение в потоке Python, из которого был введен код C.

...