Форум сайта python.su
Продолжаю мачать вас своими вопросами.
Вопрос номер раз:
Передача типа исключений в питон из буста. Пока у меня есть простая реализация, приведенная в документации к бусту:
Есть класс исключения ZException (в С++). В бусте описал так:
void translator(ZException const& x) {
PyErr_SetString(PyExc_Exception, x.getMessage().c_str());
}
register_exception_translator<ZException>(&translator);
Т.е. теперя я в питоне могу отлавливать Exception. Теперь сам вопрос:
Понятно, что у меня есть еще несколько исключений, но как я описал выше, все они пока транслируются в питоновский Exeption, а мне хотелось бы иметь свои исключения.
Например:
try:
…
exept MyCppException #исключение брошеное либой на С++
Вопрос номер два:
Я делаю обертку сетевой библиотеки (протокол не стандартный и готовых решений нет, который предоставляет возможность соединяться с базой данных), как вы поняли, используя boost. Есть порт этой либы на php. Так вот, в php, когда мы устанавливаем соединие с помошью этой библиотеки, этим соединением можно пользоваться и дальше, т.е. создается некий пул.
Опишу это кодом:
$connection = new ZConnection('host', port);
Если соединения по этому хосту и порту было установлено ранее (в предыдущем запросе), то оно продалжает использоваться дальше (интерпритатор в режиме fastCGI).
Вопрос: как можно реализовать такую функциональность в питоне? Планируется использовать django.
По поводу работы приложения, планируется использовать через fastCGI.
Спасибо! Думаю мои вопросы будут полезны не только мне.
Отредактировано (Июль 23, 2010 15:05:16)
Офлайн
1.
PyObject* pyZException = PyErr_NewException(“z.ZException”, PyExc_RuntimeError, NULL);
scope().attr(“ZException”) = pyZException;
Не наследуйте исключения от Exception, берите за базу RuntimeError - избавите себя от многих проблем в дальнейшем.
2.
Так и заводите себе этот пул внутри вашего extension.
Но вы уверены, что вам стоит так делать?
При инициализации
factory = z.Factory()
При обработке запроса
connection = factory.get('host', port)
При этом, наверное, фабрику проще написать на Питоне - не стоит тянуть С++ туда, где он не требуется.
Офлайн
Во общем, я написал вот такие вот дела:
#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>
#include <iostream>
#include “yaz4py.h”
using namespace boost::python;
using namespace std;
PyObject *cppZExceptionType = NULL;
PyObject *cppZQueryExceptionType = NULL;
PyObject *cppZResultSetExceptionType = NULL;
PyObject *cppZConnectionExceptionType = NULL;
//Трансляторы исключений
void translatorZException(ZException const& err) {
boost::python::object pythonExceptionInstance(err);
PyErr_SetObject(cppZExceptionType, incref(pythonExceptionInstance.ptr()));
}
void translatorZQueryException(ZQueryException const& err) {
boost::python::object pythonExceptionInstance(err);
PyErr_SetObject(cppZQueryExceptionType, incref(pythonExceptionInstance.ptr()));
}
void translatorZResultSetException(ZResultSetException const& err) {
boost::python::object pythonExceptionInstance(err);
PyErr_SetObject(cppZQueryExceptionType, incref(pythonExceptionInstance.ptr()));
}
void translatorZConnectionException(ZConnectionException const& err) {
boost::python::object pythonExceptionInstance(err);
PyErr_SetObject(cppZConnectionExceptionType, incref(pythonExceptionInstance.ptr()));
}
BOOST_PYTHON_MODULE(libyaz4pyboost)
{
//Исключения транслируемые в питон
//есть проблема с наследованием, т.е. исключение нельзя поймать родителем
//!надо как-то решить!
boost::python::class_<ZException>
ZExceptionClass(“ZException”,
boost::python::init<const string&, const int>())
;
ZExceptionClass.add_property(“message”, &ZException::getMessage);
ZExceptionClass.add_property(“__str__”, &ZException::getMessage);
ZExceptionClass.add_property(“code”, &ZException::getCode);
cppZExceptionType = ZExceptionClass.ptr();
boost::python::register_exception_translator<ZException>
(&translatorZException)
;
///////////////////////////////////////////////////////////////////////////
boost::python::class_<ZConnectionException, bases<ZException> >
ZConnectionExceptionClass(“ZConnectionException”,
boost::python::init<const string&, const int>())
;
ZConnectionExceptionClass.add_property(“message”, &ZConnectionException::getMessage);
ZConnectionExceptionClass.add_property(“__str__”, &ZConnectionException::getMessage);
ZConnectionExceptionClass.add_property(“code”, &ZConnectionException::getCode);
cppZConnectionExceptionType = ZConnectionExceptionClass.ptr();
boost::python::register_exception_translator<ZConnectionException>
(&translatorZConnectionException)
;
Пример класса исключения:
class ZException:public std::exception{
string message;
int code;
public:
ZException(const string &message, const int code = 0){
this->message = message;
this->code = code;
}
~ZException()throw(){ }
char const* what() const throw(){return this->message.c_str();}
const int getCode() const{
return this->code;
}
const string getMessage() const{
return this->message;
}
void setMessage(string& message){
this->message = message;
}
void setCode(const int code){
this->code = code;
}
};
class ZConnectionException:public ZException{
public:
ZConnectionException(const string &message, const int code = 0):ZException(message, code){ }
};
ZConnectionException:public наследуюется от ZException. В описании модуля я это указал.
Теперь возникает вопрос, а как мне учитывать эту иерархию в питоне. На данный момент, я могу отлавливать конкретный тип исключения, например ZConnectionException, но по родителю ZException они не ловятся. Как быть, как учитывать наследование в исключениях?
Спасибо.
Отредактировано (Июль 25, 2010 01:39:49)
Офлайн
Не стоит так делать. Напишите питоновские исключения как обычные Python C API классы.
Подглядите, например, в socket.c
Так вы сохраните питоновскую иерархию наследования.
Исключения - очень легковесные классы и много кода не потребуют.
Офлайн