diff options
author | imunkin <imunkin@yandex-team.com> | 2024-11-08 10:00:23 +0300 |
---|---|---|
committer | imunkin <imunkin@yandex-team.com> | 2024-11-08 10:12:13 +0300 |
commit | a784a2f943d6e15caa6241e2e96d80aac6dbf375 (patch) | |
tree | 05f1e5366c916b988a8afb75bdab8ddeee0f6e6d /yql/essentials/udfs/common/python/bindings/py_errors.cpp | |
parent | d70137a7b530ccaa52834274913bbb5a3d1ca06e (diff) | |
download | ydb-a784a2f943d6e15caa6241e2e96d80aac6dbf375.tar.gz |
Move yql/udfs/common/ to /yql/essentials YQL-19206
Except the following directories:
* clickhouse/client
* datetime
* knn
* roaring
commit_hash:c7da95636144d28db109d6b17ddc762e9bacb59f
Diffstat (limited to 'yql/essentials/udfs/common/python/bindings/py_errors.cpp')
-rw-r--r-- | yql/essentials/udfs/common/python/bindings/py_errors.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/yql/essentials/udfs/common/python/bindings/py_errors.cpp b/yql/essentials/udfs/common/python/bindings/py_errors.cpp new file mode 100644 index 0000000000..5741978d54 --- /dev/null +++ b/yql/essentials/udfs/common/python/bindings/py_errors.cpp @@ -0,0 +1,72 @@ +#include "py_errors.h" +#include "py_ptr.h" +#include "py_cast.h" +#include "py_utils.h" + +#include <util/generic/string.h> +#include <util/stream/output.h> + +namespace NPython { + +// this function in conjuction with code after Py_Initialize +// does approximately following: +// +// sys.stderr = StderrProxy(sys.stderr) +// +// ... +// +// sys.stderr._toggle_real_mode() +// sys.excepthook( +// sys.last_type, +// sys.last_value, +// sys.last_traceback) +// sys.stderr._get_value() +// sys.stderr._toggle_real_mode() +// +// where _toggle_real_mode, _get_value & all calls to stderr not in real mode +// are handled in a thread-safe way +// +TString GetLastErrorAsString() +{ + PyObject* etype; + PyObject* evalue; + PyObject* etraceback; + + PyErr_Fetch(&etype, &evalue, &etraceback); + + if (!etype) { + return {}; + } + + TPyObjectPtr etypePtr {etype, TPyObjectPtr::ADD_REF}; + TPyObjectPtr evaluePtr {evalue, TPyObjectPtr::ADD_REF}; + TPyObjectPtr etracebackPtr {etraceback, TPyObjectPtr::ADD_REF}; + + TPyObjectPtr stderrObject {PySys_GetObject("stderr"), TPyObjectPtr::ADD_REF}; + if (!stderrObject) { + return {}; + } + + TPyObjectPtr unused = PyObject_CallMethod(stderrObject.Get(), "_toggle_real_mode", nullptr); + + PyErr_Restore(etypePtr.Get(), evaluePtr.Get(), etracebackPtr.Get()); + // in unusual situations there may be low-level write to stderr + // (by direct C FILE* write), but that's OK + PyErr_Print(); + + TPyObjectPtr error = PyObject_CallMethod(stderrObject.Get(), "_get_value", nullptr); + if (!error) { + return {}; + } + unused.ResetSteal( + PyObject_CallMethod(stderrObject.Get(), "_toggle_real_mode", nullptr) + ); + + TString errorValue; + if (!TryPyCast(error.Get(), errorValue)) { + errorValue = TString("can't get error string from: ") += PyObjectRepr(error.Get()); + } + return errorValue; +} + +} // namspace NPython |