PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
- PyObject *pstr_msg = PyObject_Str(pvalue);
- PyObject *pstr_tb = PyObject_Str(ptraceback);
- Py_DECREF(pvalue);
- PyErr_Clear();
- String msg = PyString_AsString(pstr_msg);
- Py_DECREF(pstr_msg);
+ String msg = m_Language->ExceptionInfoToString(ptype, pvalue, ptraceback);
- String tb = PyString_AsString(pstr_tb);
- Py_DECREF(pstr_tb);
+ Py_XDECREF(ptype);
+ Py_XDECREF(pvalue);
+ Py_XDECREF(ptraceback);
- BOOST_THROW_EXCEPTION(runtime_error("Error in Python script:" + msg + " at " + tb));
+ BOOST_THROW_EXCEPTION(runtime_error("Error in Python script:" + msg));
}
Value vresult = PythonLanguage::MarshalFromPython(result);
m_MainThreadState = PyThreadState_Get();
+ m_TracebackModule = PyImport_ImportModule("traceback");
+
m_NativeModule = Py_InitModule("ire", m_NativeMethodDef);
(void) PyThreadState_Swap(NULL);
}
}
+String PythonLanguage::ExceptionInfoToString(PyObject *type, PyObject *exc, PyObject *tb) const
+{
+ PyObject *tb_dict = PyModule_GetDict(m_TracebackModule);
+ PyObject *format_exception = PyDict_GetItemString(tb_dict, "format_exception");
+
+ if (!PyCallable_Check(format_exception))
+ return "Failed to format exception information.";
+
+ PyObject *result = PyObject_CallFunctionObjArgs(format_exception, type, exc, tb);
+
+ Py_DECREF(format_exception);
+ Py_DECREF(tb_dict);
+
+ if (!result || !PyString_Check(result)) {
+ Py_XDECREF(result);
+
+ return "format_exception() returned something that is not a string.";
+ }
+
+ String msg = PyString_AsString(result);
+
+ Py_DECREF(result);
+
+ return msg;
+}
+
PyObject *PythonLanguage::PyCallNativeFunction(PyObject *self, PyObject *args)
{
assert(PyString_Check(self));
static PyObject *MarshalToPython(const Value& value);
static Value MarshalFromPython(PyObject *value);
+ String ExceptionInfoToString(PyObject *type, PyObject *exc, PyObject *tb) const;
private:
PyThreadState *m_MainThreadState;
PyObject *m_NativeModule;
+ PyObject *m_TracebackModule;
static PythonInterpreter *m_CurrentInterpreter;
void RegisterNativeFunction(const String& name, const ScriptFunction::Ptr& function);