aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/python/lib
diff options
context:
space:
mode:
authorGravatar Eugene Brevdo <ebrevdo@google.com>2018-03-07 14:53:49 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-03-07 14:57:37 -0800
commitfffb7b59f5695b36af4e03c1dd8eadff3fd0024c (patch)
treea61326d198714325a12f4b6f4f391dff5e256db9 /tensorflow/python/lib
parent3152a96ff23de6790d0faf83f823e9c8dbc51c53 (diff)
py_func attaches full stack traces when an error is raised.
This should help debugging errors that occur inside a py_func. PiperOrigin-RevId: 188238495
Diffstat (limited to 'tensorflow/python/lib')
-rw-r--r--tensorflow/python/lib/core/py_util.cc59
1 files changed, 57 insertions, 2 deletions
diff --git a/tensorflow/python/lib/core/py_util.cc b/tensorflow/python/lib/core/py_util.cc
index 2635694e23..00cbf0c532 100644
--- a/tensorflow/python/lib/core/py_util.cc
+++ b/tensorflow/python/lib/core/py_util.cc
@@ -41,6 +41,55 @@ const char* ClassName(PyObject* py) {
} // end namespace
+// Returns a PyObject containing a string, or null
+void TryAppendTraceback(PyObject* ptype, PyObject* pvalue, PyObject* ptraceback,
+ string* out) {
+ // The "traceback" module is assumed to be imported already by script_ops.py.
+ PyObject* tb_module = PyImport_AddModule("traceback");
+
+ if (!tb_module) {
+ return;
+ }
+
+ PyObject* format_exception =
+ PyObject_GetAttrString(tb_module, "format_exception");
+
+ if (!format_exception) {
+ return;
+ }
+
+ if (!PyCallable_Check(format_exception)) {
+ Py_DECREF(format_exception);
+ return;
+ }
+
+ PyObject* ret_val = PyObject_CallFunctionObjArgs(format_exception, ptype,
+ pvalue, ptraceback, nullptr);
+ Py_DECREF(format_exception);
+
+ if (!ret_val) {
+ return;
+ }
+
+ if (!PyList_Check(ret_val)) {
+ Py_DECREF(ret_val);
+ return;
+ }
+
+ Py_ssize_t n = PyList_GET_SIZE(ret_val);
+ for (Py_ssize_t i = 0; i < n; ++i) {
+ PyObject* v = PyList_GET_ITEM(ret_val, i);
+#if PY_MAJOR_VERSION < 3
+ strings::StrAppend(out, PyString_AS_STRING(v), "\n");
+#else
+ strings::StrAppend(out, PyUnicode_AsUTF8(v), "\n");
+#endif
+ }
+
+ // Iterate through ret_val.
+ Py_DECREF(ret_val);
+}
+
string PyExceptionFetch() {
CHECK(PyErr_Occurred())
<< "Must only call PyExceptionFetch after an exception.";
@@ -52,14 +101,20 @@ string PyExceptionFetch() {
string err = ClassName(ptype);
if (pvalue) {
PyObject* str = PyObject_Str(pvalue);
+
if (str) {
#if PY_MAJOR_VERSION < 3
- strings::StrAppend(&err, ": ", PyString_AS_STRING(str));
+ strings::StrAppend(&err, ": ", PyString_AS_STRING(str), "\n");
#else
- strings::StrAppend(&err, ": ", PyUnicode_AsUTF8(str));
+ strings::StrAppend(&err, ": ", PyUnicode_AsUTF8(str), "\n");
#endif
Py_DECREF(str);
+ } else {
+ strings::StrAppend(&err, "(unknown error message)\n");
}
+
+ TryAppendTraceback(ptype, pvalue, ptraceback, &err);
+
Py_DECREF(pvalue);
}
Py_DECREF(ptype);