Skip to content
Snippets Groups Projects
Commit 6e15fc22 authored by Pospelov, Gennady's avatar Pospelov, Gennady
Browse files

PyEmbedded methods to retrieve Python stack trace.

parent 05d0cfbb
No related branches found
No related tags found
No related merge requests found
......@@ -38,7 +38,7 @@ std::string PyEmbeddedUtils::toString(PyObject* obj, bool decref)
return result;
}
std::vector<std::string> PyEmbeddedUtils::toVectorString(PyObject* obj, bool decref)
std::vector<std::string> PyEmbeddedUtils::toVectorString(PyObject* obj)
{
std::vector<std::string> result;
......@@ -58,9 +58,6 @@ std::vector<std::string> PyEmbeddedUtils::toVectorString(PyObject* obj, bool dec
throw std::runtime_error("PyEmbeddedUtils::toVectorString() -> Error. Unexpected object.");
}
if (decref)
Py_DECREF(obj);
return result;
}
......@@ -116,3 +113,79 @@ void PyEmbeddedUtils::import_bornagain(const std::string& path)
}
}
std::string PyEmbeddedUtils::pythonRuntimeInfo()
{
Py_InitializeEx(0);
std::stringstream result;
// Runtime environment
result << std::string(60, '=') << "\n";
result << "PATH: " << SysUtils::getenv("PATH") << "\n";
result << "PYTHONPATH: " << SysUtils::getenv("PYTHONPATH") << "\n";
result << "PYTHONHOME: " << SysUtils::getenv("PYTHONHOME") << "\n";
// Embedded Python details
result << "Py_GetProgramName(): "
<< PyEmbeddedUtils::toString(Py_GetProgramName()) << "\n";
result << "Py_GetPath(): "
<< PyEmbeddedUtils::toString(Py_GetPath()) << "\n";
result << "Py_GetProgramFullPath(): "
<< PyEmbeddedUtils::toString(Py_GetProgramFullPath()) << "\n";
result << "Py_GetPythonHome(): "
<< PyEmbeddedUtils::toString(Py_GetPythonHome()) << "\n";
// Runtime Python's sys.path
PyObject *sysPath = PySys_GetObject((char*)"path");
auto content = PyEmbeddedUtils::toVectorString(sysPath);
result << "sys.path: ";
for (auto s : content)
result << s << ",";
result << "\n";
return result.str();
}
// Attempt to retrieve Python stack trace
// https://stackoverflow.com/questions/1796510/accessing-a-python-traceback-from-the-c-api
std::string PyEmbeddedUtils::pythonStackTrace()
{
std::stringstream result;
if (PyErr_Occurred()) {
PyObject *ptype, *pvalue, *ptraceback, *pystr;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
pystr = PyObject_Str(pvalue);
if (char* str = PyString_AsString(pystr))
result << std::string(str) << "\n";
PyObject* module_name = PyString_FromString("traceback");
PyObject* pyth_module = PyImport_Import(module_name);
Py_DECREF(module_name);
if (pyth_module) {
result << "\n";
PyObject* pyth_func = PyObject_GetAttrString(pyth_module, "format_exception");
if (pyth_func && PyCallable_Check(pyth_func)) {
PyObject* pyth_val;
pyth_val = PyObject_CallFunctionObjArgs(pyth_func, ptype, pvalue, ptraceback, NULL);
pystr = PyObject_Str(pyth_val);
if (char* str = PyString_AsString(pystr))
result << std::string(str);
Py_DECREF(pyth_val);
}
result << "\n";
}
}
result << "\n";
result << pythonRuntimeInfo();
result << "\n";
return result.str();
}
......@@ -33,7 +33,7 @@ BA_CORE_API_ std::string toString(PyObject* obj, bool decref = true);
//! Converts PyObject into vector of strings, if possible, or throws exception.
//! @param decref To automatically decrease reference counter after data is processed.
BA_CORE_API_ std::vector<std::string> toVectorString(PyObject* obj, bool decref = true);
BA_CORE_API_ std::vector<std::string> toVectorString(PyObject* obj);
//! Converts char to string. In the case of nullptr will return an empty string.
BA_CORE_API_ std::string toString(char* c);
......@@ -42,6 +42,11 @@ BA_CORE_API_ std::string toString(wchar_t* c);
//! Imports BornAgain from given location. If path is empty, tries to rely on PYTHONPATH.
BA_CORE_API_ void import_bornagain(const std::string& path = std::string());
//! Returns multi-line string representing PATH, PYTHONPATH, sys.path and other info.
BA_CORE_API_ std::string pythonRuntimeInfo();
//! Returns string representing python stack trace.
BA_CORE_API_ std::string pythonStackTrace();
}
#endif
......
......@@ -70,8 +70,12 @@ std::vector<std::string> PyImport::listOfFunctions(const std::string& script,
// create a module
PyObject* pModule = PyImport_ExecCodeModule((char *)"test" , pCompiledFn ) ;
if (!pModule)
throw std::runtime_error("Can't exec module");
if (!pModule) {
std::stringstream buf;
buf << "Can't exec module" << "\n";
buf << PyEmbeddedUtils::pythonStackTrace() << "\n";
throw std::runtime_error(buf.str());
}
PyObject *dict = PyModule_GetDict(pModule);
if (!dict)
......
......@@ -145,6 +145,7 @@ QString PyImportAssistant::getPySampleFunctionName(const QString& snippet)
funcList = GUIHelpers::fromStdStrings(funcs);
} catch (const std::exception& ex) {
QApplication::restoreOverrideCursor();
QString message("Exception thrown while executing a Python code.\n\n");
message += QString::fromStdString(std::string(ex.what()));
GUIHelpers::warning(m_mainWindow, "Python failure", message);
......
......@@ -43,32 +43,8 @@ bool SysPath::runTest()
// BornAgain build
std::cout << "buildLibDir(): " << BABuild::buildLibDir() << std::endl;
// Runtime environment
std::cout << "PATH: " << SysUtils::getenv("PATH") << std::endl;
std::cout << "PYTHONPATH: " << SysUtils::getenv("PYTHONPATH") << std::endl;
std::cout << "PYTHONHOME: " << SysUtils::getenv("PYTHONHOME") << std::endl;
Py_Initialize();
// Embedded Python details
std::cout << "Py_GetProgramName(): "
<< PyEmbeddedUtils::toString(Py_GetProgramName()) << std::endl;
std::cout << "Py_GetPath(): "
<< PyEmbeddedUtils::toString(Py_GetPath()) << std::endl;
std::cout << "Py_GetProgramFullPath(): "
<< PyEmbeddedUtils::toString(Py_GetProgramFullPath()) << std::endl;
std::cout << "Py_GetPythonHome(): "
<< PyEmbeddedUtils::toString(Py_GetPythonHome()) << std::endl;
// Runtime Python's sys.path
PyObject *sysPath = PySys_GetObject((char*)"path");
auto content = PyEmbeddedUtils::toVectorString(sysPath);
std::cout << "sys.path: ";
for (auto s : content)
std::cout << s << ",";
std::cout << std::endl;
Py_Finalize();
// Runtime info
auto content = PyEmbeddedUtils::pythonRuntimeInfo();
return !content.empty();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment