| 96 | bool is_active() { return Py_IsInitialized(); } |
| 97 | |
| 98 | void check_error(bool force_error) |
| 99 | { |
| 100 | global_interpreter_lock gil; |
| 101 | if (force_error || PyErr_Occurred()) { |
| 102 | |
| 103 | // Get error information from Python session |
| 104 | PyObject *type_ptr, *value_ptr, *traceback_ptr; |
| 105 | PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr); |
| 106 | object type(type_ptr), value(value_ptr), traceback(traceback_ptr); |
| 107 | |
| 108 | // Construct error message |
| 109 | std::ostringstream err; |
| 110 | err << "detected Python error"; |
| 111 | if (value != nullptr) { |
| 112 | object msg = PyObject_Repr(value); |
| 113 | msg = PyUnicode_AsEncodedString(msg, "utf-8", "Error -"); |
| 114 | err << " (" << PyBytes_AS_STRING(msg.get()) << ")"; |
| 115 | } |
| 116 | |
| 117 | // Print Python traceback if available |
| 118 | if (traceback != nullptr) { |
| 119 | |
| 120 | // Format traceback |
| 121 | object module = PyImport_ImportModule("traceback"); |
| 122 | object func = PyObject_GetAttrString(module, "format_tb"); |
| 123 | object message = |
| 124 | PyObject_CallMethod(module, "format_tb", "(O)", traceback.get()); |
| 125 | |
| 126 | // Print traceback |
| 127 | err << "\n\n" |
| 128 | << "Python traceback:"; |
| 129 | object iter = PyObject_GetIter(message); |
| 130 | for (object line = PyIter_Next(iter); line != nullptr; |
| 131 | line = PyIter_Next(iter)) { |
| 132 | const char* line_ = PyUnicode_AsUTF8(line); |
| 133 | err << "\n" << (line_ ? line_ : ""); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | // Clean up and throw exception |
| 138 | PyErr_Restore(type.release(), value.release(), traceback.release()); |
| 139 | PyErr_Clear(); |
| 140 | LBANN_ERROR(err.str()); |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | // --------------------------------------------- |
| 145 | // global_interpreter_lock class |
no test coverage detected