Expose payloads information to python users.

PiperOrigin-RevId: 360067738
Change-Id: Idf44b8015f2e29032e60adea288222b6c4bd9b53
This commit is contained in:
A. Unique TensorFlower 2021-02-28 14:07:19 -08:00 committed by TensorFlower Gardener
parent 59ff97c07b
commit fc1bdb3a68
50 changed files with 477 additions and 125 deletions

View File

@ -119,6 +119,10 @@
`tf.config.experimental.get_memory_usage` in favor of this new function.
* Extended `tf.config.experimental.enable_tensor_float_32_execution` to
control Tensor-Float-32 evaluation in RNNs.
* Added a 'experimental_payloads' field to tf.errors.OpError and
its subclasses to support more detailed error reporting.
This is inspired from Abseil Status payloads:
https://github.com/abseil/abseil-cpp/blob/master/absl/status/status.h
* `tf.summary`:
* New `tf.summary.graph` allows manual write of TensorFlow graph

View File

@ -79,6 +79,7 @@ void Set_TF_Status_from_Status(TF_Status* tf_status, const Status& status) {
assert(0);
break;
}
tf_status->status.ReplaceAllPayloads(status.GetAllPayloads());
}
Status StatusFromTF_Status(const TF_Status* tf_status) {

View File

@ -24,6 +24,8 @@ namespace {
TEST(StatusHelper, TestStatusHelper) {
TF_Status* s = TF_NewStatus();
Status cc_status(errors::InvalidArgument("some error"));
cc_status.SetPayload("key1", "value1");
cc_status.SetPayload("key2", "value2");
Set_TF_Status_from_Status(s, cc_status);
ASSERT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s));
ASSERT_EQ(std::string("some error"), TF_Message(s));
@ -32,6 +34,9 @@ TEST(StatusHelper, TestStatusHelper) {
ASSERT_FALSE(another_cc_status.ok());
ASSERT_EQ(std::string("some error"), another_cc_status.error_message());
ASSERT_EQ(error::INVALID_ARGUMENT, another_cc_status.code());
// Ensure the payloads are not lost during conversions
ASSERT_EQ(cc_status.GetPayload("key1"), another_cc_status.GetPayload("key1"));
ASSERT_EQ(cc_status.GetPayload("key2"), another_cc_status.GetPayload("key2"));
TF_DeleteStatus(s);
}

View File

@ -202,6 +202,54 @@ TEST(Status, ErasePayloadRemovesIt) {
ASSERT_EQ(s.GetPayload("Error key"), tensorflow::StringPiece());
}
TEST(Status, GetAllPayloads) {
Status s_error(error::INTERNAL, "Error message");
s_error.SetPayload("Error key", "foo");
auto payloads_error_status = s_error.GetAllPayloads();
ASSERT_EQ(payloads_error_status.size(), 1);
ASSERT_EQ(payloads_error_status["Error key"], "foo");
Status s_ok = Status();
auto payloads_ok_status = s_ok.GetAllPayloads();
ASSERT_TRUE(payloads_ok_status.empty());
}
TEST(Status, OKStatusReplaceAllPayloadsFromErrorStatus) {
// An OK status will should not change after ReplaceAllPayloads() calls.
Status s_error(error::INTERNAL, "Error message");
s_error.SetPayload("Error key", "foo");
Status s_ok = Status();
s_ok.ReplaceAllPayloads(s_error.GetAllPayloads());
auto payloads_ok_status = s_ok.GetAllPayloads();
ASSERT_TRUE(payloads_ok_status.empty());
}
TEST(Status, ErrorStatusReplaceAllPayloadsFromOKStatus) {
// An ReplaceAllPayloads() call should not take effect from empty inputs.
Status s_error(error::INTERNAL, "Error message");
s_error.SetPayload("Error key", "foo");
Status s_ok = Status();
s_error.ReplaceAllPayloads(s_ok.GetAllPayloads());
ASSERT_EQ(s_error.GetPayload("Error key"), "foo");
}
TEST(Status, ErrorStatusReplaceAllPayloadsFromErrorStatus) {
Status s_error1(error::INTERNAL, "Error message");
s_error1.SetPayload("Error key 1", "foo");
s_error1.SetPayload("Error key 2", "bar");
Status s_error2(error::INTERNAL, "Error message");
s_error2.SetPayload("Error key", "bar");
ASSERT_EQ(s_error2.GetPayload("Error key"), "bar");
s_error2.ReplaceAllPayloads(s_error1.GetAllPayloads());
ASSERT_EQ(s_error2.GetPayload("Error key 1"), "foo");
ASSERT_EQ(s_error2.GetPayload("Error key 2"), "bar");
auto payloads_error_status = s_error2.GetAllPayloads();
ASSERT_EQ(payloads_error_status.size(), 2);
}
static void BM_TF_CHECK_OK(::testing::benchmark::State& state) {
tensorflow::Status s = (state.max_iterations < 0)
? errors::InvalidArgument("Invalid")

View File

@ -222,6 +222,19 @@ bool Status::ErasePayload(tensorflow::StringPiece type_url) {
return true;
}
const std::unordered_map<std::string, std::string> Status::GetAllPayloads()
const {
if (ok()) return {};
return state_->payloads;
}
void Status::ReplaceAllPayloads(
const std::unordered_map<std::string, std::string>& payloads) {
if (ok() || payloads.empty()) return;
if (state_ == nullptr) state_ = std::make_unique<State>();
state_->payloads = payloads;
}
std::ostream& operator<<(std::ostream& os, const Status& x) {
os << x.ToString();
return os;

View File

@ -113,7 +113,7 @@ class Status {
// Sets the payload for a non-ok status using a `type_url` key, overwriting
// any existing payload for that `type_url`.
//
// NOTE: This function does nothing if the Status is ok.
// This function does nothing if the Status is ok.
void SetPayload(tensorflow::StringPiece type_url,
tensorflow::StringPiece payload);
@ -121,6 +121,15 @@ class Status {
// the payload was present.
bool ErasePayload(tensorflow::StringPiece type_url);
// Returns all the payload information.
// Returns an empty result if status is ok.
const std::unordered_map<std::string, std::string> GetAllPayloads() const;
// Copies all the payloads using the input and discards existing payloads.
// Does nothing if status is ok or 'payloads' is empty.
void ReplaceAllPayloads(
const std::unordered_map<std::string, std::string>& payloads);
private:
static const std::string& empty_string();
static const std::vector<StackFrame>& empty_stack_trace();

View File

@ -765,6 +765,7 @@ py_library(
"//tensorflow/python/util:_pywrap_tfprof",
"//tensorflow/python/util:_pywrap_util_port",
":_pywrap_utils",
":_errors_test_helper",
":composite_tensor",
":config",
":convert_to_constants",
@ -1924,6 +1925,7 @@ tf_py_test(
main = "framework/errors_test.py",
python_version = "PY3",
deps = [
":_errors_test_helper",
":client_testlib",
":errors",
"//tensorflow/core:protos_all_py",
@ -5119,6 +5121,17 @@ tf_python_pybind_extension(
],
)
tf_python_pybind_extension(
name = "_errors_test_helper",
srcs = ["framework/errors_test_helper.cc"],
module_name = "_errors_test_helper",
deps = [
"//tensorflow/core/platform:status",
"//tensorflow/python/lib/core:pybind11_status",
"@pybind11",
],
)
cuda_py_tests(
name = "device_lib_test",
size = "small",

View File

@ -106,25 +106,10 @@ class _ErrorMetadata(error_utils.ErrorMetadataBase):
message = self.get_message()
init_args = tuple(init_argspec.args)
# At the time of this writing, TF errors either take 3 or 4 arguments,
# with the fourth being error_code.
if init_args == ('self', 'node_def', 'op', 'message', 'error_code'):
return preferred_type(
node_def=source_error.node_def,
op=source_error.op,
message=message,
error_code=self.error_code)
elif init_args == ('self', 'node_def', 'op', 'message'):
if 'error_code' in init_argspec.kwonlyargs:
return preferred_type(
node_def=source_error.node_def,
op=source_error.op,
message=message,
errro_code=self.error_code)
else:
return preferred_type(
node_def=source_error.node_def,
op=source_error.op,
message=message)
# the argument '*args' may or may not be used.
if init_args == ('self', 'node_def', 'op', 'message'):
return preferred_type(source_error.node_def, source_error.op, message,
source_error.experimental_payloads)
elif preferred_type in (errors.PyCTError, AutoGraphError, ConversionError,
StagingError, errors_impl.InaccessibleTensorError,
@ -159,8 +144,8 @@ def _attach_error_metadata(e, f):
cause_tb = traceback.extract_tb(sys.exc_info()[2])[1:]
e.ag_error_metadata = _ErrorMetadata(
cause_tb, metadata, message, source_map, __file__)
e.ag_error_metadata = _ErrorMetadata(cause_tb, metadata, message, source_map,
__file__)
class StackTraceMapper(tf_stack.StackTraceMapper):
@ -312,11 +297,7 @@ def is_autograph_artifact(entity):
return hasattr(entity, 'autograph_info__')
def converted_call(f,
args,
kwargs,
caller_fn_scope=None,
options=None):
def converted_call(f, args, kwargs, caller_fn_scope=None, options=None):
"""Converts a function call inline.
For internal use only.
@ -437,8 +418,7 @@ def converted_call(f,
return _fall_back_unconverted(f, args, kwargs, options, e)
if not hasattr(target_entity, '__code__'):
logging.log(2, 'Permanently allowed: %s: native binding',
target_entity)
logging.log(2, 'Permanently allowed: %s: native binding', target_entity)
return _call_unconverted(f, args, kwargs, options)
elif (hasattr(target_entity.__code__, 'co_filename') and
target_entity.__code__.co_filename == '<string>'):
@ -611,6 +591,7 @@ def tf_convert(f, ctx, convert_by_default=True, user_requested=False):
def call_with_unspecified_conversion_status(func):
"""Decorator that resets the conversion context to the unspecified status."""
def wrapper(*args, **kwargs):
with ag_ctx.ControlStatusCtx(status=ag_ctx.Status.UNSPECIFIED):
return func(*args, **kwargs)

View File

@ -33,6 +33,7 @@ import types
import numpy as np
import six
from tensorflow.python import _errors_test_helper
from tensorflow.python.autograph.core import ag_ctx
from tensorflow.python.autograph.core import converter
from tensorflow.python.autograph.core import converter_testing
@ -46,6 +47,7 @@ from tensorflow.python.data.ops import dataset_ops
from tensorflow.python.eager import def_function
from tensorflow.python.eager import function
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import errors as tf_errors
from tensorflow.python.framework import ops
from tensorflow.python.framework import test_util
from tensorflow.python.ops import math_ops
@ -1260,6 +1262,35 @@ class ApiTest(test.TestCase):
self.assertEqual(5, tc.two_args(2))
def test_raise_from_func_graph(self):
@def_function.function
def raise_from_tf_function(n):
_errors_test_helper.TestRaiseFromStatus(n)
for code, expected_exception in [
(1, tf_errors.CancelledError),
(2, tf_errors.UnknownError),
(3, tf_errors.InvalidArgumentError),
(4, tf_errors.DeadlineExceededError),
(5, tf_errors.NotFoundError),
(6, tf_errors.AlreadyExistsError),
(7, tf_errors.PermissionDeniedError),
(16, tf_errors.UnauthenticatedError),
(8, tf_errors.ResourceExhaustedError),
(9, tf_errors.FailedPreconditionError),
(10, tf_errors.AbortedError),
(11, tf_errors.OutOfRangeError),
(12, tf_errors.UnimplementedError),
(13, tf_errors.InternalError),
(14, tf_errors.UnavailableError),
(15, tf_errors.DataLossError),
]:
with self.assertRaises(expected_exception) as error:
raise_from_tf_function(code)
self.assertEqual(error.exception.experimental_payloads['key1'], 'value1')
self.assertEqual(error.exception.experimental_payloads['key2'], 'value2')
if __name__ == '__main__':
os.environ['AUTOGRAPH_STRICT_CONVERSION'] = '1'

View File

@ -66,6 +66,7 @@ cc_library(
"//tensorflow/python:ndarray_tensor_bridge",
"//tensorflow/python:numpy_lib",
"//tensorflow/python:py_exception_registry",
"//tensorflow/python:pybind11_status",
"//tensorflow/python/lib/core:py_seq_tensor",
"//tensorflow/python/lib/core:py_util",
"//tensorflow/python/lib/core:safe_ptr",

View File

@ -38,6 +38,7 @@ limitations under the License.
#include "tensorflow/python/lib/core/numpy.h"
#include "tensorflow/python/lib/core/py_exception_registry.h"
#include "tensorflow/python/lib/core/py_seq_tensor.h"
#include "tensorflow/python/lib/core/pybind11_status.h"
#include "tensorflow/python/lib/core/safe_ptr.h"
// forward declare
@ -186,13 +187,9 @@ int ConvertDeviceName(PyObject* obj, const char** dst) {
return 1;
}
void RaiseExceptionTypeFromTFStatus(TF_Status* status) {
TF_Code code = TF_GetCode(status);
PyObject* exception = tensorflow::PyExceptionRegistry::Lookup(code);
PyErr_SetObject(exception,
pybind11::make_tuple(pybind11::none(), pybind11::none(),
TF_Message(status))
.ptr());
void RaiseExceptionTypeFromTFStatus(TF_Status* tf_status) {
auto status = tensorflow::StatusFromTF_Status(tf_status);
SetRegisteredErrFromStatus(status);
}
} // namespace

View File

@ -67,7 +67,7 @@ class OpError(Exception):
of `OpError` from the `tf.errors` module.
"""
def __init__(self, node_def, op, message, error_code):
def __init__(self, node_def, op, message, error_code, *args):
"""Creates a new `OpError` indicating that a particular op failed.
Args:
@ -76,12 +76,19 @@ class OpError(Exception):
op: The `ops.Operation` that failed, if known; otherwise None.
message: The message string describing the failure.
error_code: The `error_codes_pb2.Code` describing the error.
*args: If not empty, it should contain a dictionary describing details
about the error. This argument is inspired by Abseil payloads:
https://github.com/abseil/abseil-cpp/blob/master/absl/status/status.h
"""
super(OpError, self).__init__()
self._node_def = node_def
self._op = op
self._message = message
self._error_code = error_code
if args:
self._experimental_payloads = args[0]
else:
self._experimental_payloads = {}
def __reduce__(self):
# Allow the subclasses to accept less arguments in their __init__.
@ -120,10 +127,19 @@ class OpError(Exception):
"""The `NodeDef` proto representing the op that failed."""
return self._node_def
@property
def experimental_payloads(self):
"""A dictionary describing the details of the error."""
return self._experimental_payloads
def __str__(self):
if self._op is not None:
output = ["%s\n\nOriginal stack trace for %r:\n" % (self.message,
self._op.name,)]
output = [
"%s\n\nOriginal stack trace for %r:\n" % (
self.message,
self._op.name,
)
]
curr_traceback_list = traceback.format_list(
_compact_stack_trace(self._op))
output.extend(curr_traceback_list)
@ -132,8 +148,8 @@ class OpError(Exception):
# pylint: enable=protected-access
while original_op is not None:
output.append(
"\n...which was originally created as op %r, defined at:\n"
% (original_op.name,))
"\n...which was originally created as op %r, defined at:\n" %
(original_op.name,))
prev_traceback_list = curr_traceback_list
curr_traceback_list = traceback.format_list(
_compact_stack_trace(original_op))
@ -157,9 +173,10 @@ class OpError(Exception):
else:
if is_eliding:
if elide_count > 0:
output.extend(
["[elided %d identical lines from previous traceback]\n"
% (elide_count - 1,), last_elided_line])
output.extend([
"[elided %d identical lines from previous traceback]\n" %
(elide_count - 1,), last_elided_line
])
is_eliding = False
output.extend(line)
@ -228,9 +245,12 @@ class CancelledError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates a `CancelledError`."""
super(CancelledError, self).__init__(node_def, op, message, CANCELLED)
super(CancelledError, self).__init__(node_def, op, message, CANCELLED,
*args)
# pylint: enable=line-too-long
@ -247,9 +267,9 @@ class UnknownError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message, error_code=UNKNOWN):
def __init__(self, node_def, op, message, *args):
"""Creates an `UnknownError`."""
super(UnknownError, self).__init__(node_def, op, message, error_code)
super(UnknownError, self).__init__(node_def, op, message, UNKNOWN, *args)
@tf_export("errors.InvalidArgumentError")
@ -267,10 +287,10 @@ class InvalidArgumentError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `InvalidArgumentError`."""
super(InvalidArgumentError, self).__init__(node_def, op, message,
INVALID_ARGUMENT)
INVALID_ARGUMENT, *args)
@tf_export("errors.DeadlineExceededError")
@ -282,10 +302,10 @@ class DeadlineExceededError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates a `DeadlineExceededError`."""
super(DeadlineExceededError, self).__init__(node_def, op, message,
DEADLINE_EXCEEDED)
DEADLINE_EXCEEDED, *args)
@tf_export("errors.NotFoundError")
@ -300,9 +320,9 @@ class NotFoundError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates a `NotFoundError`."""
super(NotFoundError, self).__init__(node_def, op, message, NOT_FOUND)
super(NotFoundError, self).__init__(node_def, op, message, NOT_FOUND, *args)
@tf_export("errors.AlreadyExistsError")
@ -317,10 +337,10 @@ class AlreadyExistsError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `AlreadyExistsError`."""
super(AlreadyExistsError, self).__init__(node_def, op, message,
ALREADY_EXISTS)
ALREADY_EXISTS, *args)
@tf_export("errors.PermissionDeniedError")
@ -335,10 +355,10 @@ class PermissionDeniedError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates a `PermissionDeniedError`."""
super(PermissionDeniedError, self).__init__(node_def, op, message,
PERMISSION_DENIED)
PERMISSION_DENIED, *args)
@tf_export("errors.UnauthenticatedError")
@ -350,10 +370,10 @@ class UnauthenticatedError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `UnauthenticatedError`."""
super(UnauthenticatedError, self).__init__(node_def, op, message,
UNAUTHENTICATED)
UNAUTHENTICATED, *args)
@tf_export("errors.ResourceExhaustedError")
@ -366,10 +386,10 @@ class ResourceExhaustedError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates a `ResourceExhaustedError`."""
super(ResourceExhaustedError, self).__init__(node_def, op, message,
RESOURCE_EXHAUSTED)
RESOURCE_EXHAUSTED, *args)
@tf_export("errors.FailedPreconditionError")
@ -383,10 +403,10 @@ class FailedPreconditionError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates a `FailedPreconditionError`."""
super(FailedPreconditionError, self).__init__(node_def, op, message,
FAILED_PRECONDITION)
FAILED_PRECONDITION, *args)
@tf_export("errors.AbortedError")
@ -402,9 +422,9 @@ class AbortedError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `AbortedError`."""
super(AbortedError, self).__init__(node_def, op, message, ABORTED)
super(AbortedError, self).__init__(node_def, op, message, ABORTED, *args)
@tf_export("errors.OutOfRangeError")
@ -420,10 +440,10 @@ class OutOfRangeError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `OutOfRangeError`."""
super(OutOfRangeError, self).__init__(node_def, op, message,
OUT_OF_RANGE)
super(OutOfRangeError, self).__init__(node_def, op, message, OUT_OF_RANGE,
*args)
@tf_export("errors.UnimplementedError")
@ -439,10 +459,10 @@ class UnimplementedError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `UnimplementedError`."""
super(UnimplementedError, self).__init__(node_def, op, message,
UNIMPLEMENTED)
UNIMPLEMENTED, *args)
@tf_export("errors.InternalError")
@ -455,9 +475,9 @@ class InternalError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `InternalError`."""
super(InternalError, self).__init__(node_def, op, message, INTERNAL)
super(InternalError, self).__init__(node_def, op, message, INTERNAL, *args)
@tf_export("errors.UnavailableError")
@ -469,10 +489,10 @@ class UnavailableError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates an `UnavailableError`."""
super(UnavailableError, self).__init__(node_def, op, message,
UNAVAILABLE)
super(UnavailableError, self).__init__(node_def, op, message, UNAVAILABLE,
*args)
@tf_export("errors.DataLossError")
@ -486,9 +506,9 @@ class DataLossError(OpError):
@@__init__
"""
def __init__(self, node_def, op, message):
def __init__(self, node_def, op, message, *args):
"""Creates a `DataLossError`."""
super(DataLossError, self).__init__(node_def, op, message, DATA_LOSS)
super(DataLossError, self).__init__(node_def, op, message, DATA_LOSS, *args)
_CODE_TO_EXCEPTION_CLASS = {
@ -513,7 +533,8 @@ _CODE_TO_EXCEPTION_CLASS = {
_pywrap_py_exception_registry.PyExceptionRegistry_Init(_CODE_TO_EXCEPTION_CLASS)
_EXCEPTION_CLASS_TO_CODE = {
class_: code for code, class_ in _CODE_TO_EXCEPTION_CLASS.items()}
class_: code for code, class_ in _CODE_TO_EXCEPTION_CLASS.items()
}
@tf_export(v1=["errors.exception_type_from_error_code"])
@ -555,8 +576,7 @@ class raise_exception_on_not_ok_status(object):
try:
if c_api.TF_GetCode(self.status.status) != 0:
raise _make_specific_exception(
None, None,
compat.as_text(c_api.TF_Message(self.status.status)),
None, None, compat.as_text(c_api.TF_Message(self.status.status)),
c_api.TF_GetCode(self.status.status))
# Delete the underlying status object from memory otherwise it stays alive
# as there is a reference to status from this from the traceback due to

View File

@ -23,6 +23,7 @@ import pickle
import warnings
from tensorflow.core.lib.core import error_codes_pb2
from tensorflow.python import _errors_test_helper
from tensorflow.python.framework import c_api_util
from tensorflow.python.framework import errors
from tensorflow.python.framework import errors_impl
@ -146,6 +147,53 @@ class ErrorsTest(test.TestCase):
self.assertEqual(exc.message, unpickled.message)
self.assertEqual(exc.error_code, unpickled.error_code)
def testErrorPayloadsFromStatus(self):
for code, expected_exception in [
(1, errors.CancelledError),
(2, errors.UnknownError),
(3, errors.InvalidArgumentError),
(4, errors.DeadlineExceededError),
(5, errors.NotFoundError),
(6, errors.AlreadyExistsError),
(7, errors.PermissionDeniedError),
(16, errors.UnauthenticatedError),
(8, errors.ResourceExhaustedError),
(9, errors.FailedPreconditionError),
(10, errors.AbortedError),
(11, errors.OutOfRangeError),
(12, errors.UnimplementedError),
(13, errors.InternalError),
(14, errors.UnavailableError),
(15, errors.DataLossError),
]:
with self.assertRaises(expected_exception) as error:
_errors_test_helper.TestRaiseFromStatus(code)
self.assertEqual(error.exception.experimental_payloads["key1"], "value1")
self.assertEqual(error.exception.experimental_payloads["key2"], "value2")
def testErrorPayloadsDefaultValue(self):
for exception_type in [
(errors.CancelledError),
(errors.UnknownError),
(errors.InvalidArgumentError),
(errors.DeadlineExceededError),
(errors.NotFoundError),
(errors.AlreadyExistsError),
(errors.PermissionDeniedError),
(errors.UnauthenticatedError),
(errors.ResourceExhaustedError),
(errors.FailedPreconditionError),
(errors.AbortedError),
(errors.OutOfRangeError),
(errors.UnimplementedError),
(errors.InternalError),
(errors.UnavailableError),
(errors.DataLossError),
]:
e = exception_type(None, None, None)
self.assertEqual(type(e.experimental_payloads), dict)
self.assertEqual(len(e.experimental_payloads), 0)
if __name__ == "__main__":
test.main()

View File

@ -0,0 +1,31 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "pybind11/pybind11.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow/python/lib/core/pybind11_status.h"
namespace tensorflow {
PYBIND11_MODULE(_errors_test_helper, m) {
m.def("TestRaiseFromStatus", [](int code) {
tensorflow::Status status(static_cast<tensorflow::error::Code>(code),
"test message");
status.SetPayload("key1", "value1");
status.SetPayload("key2", "value2");
MaybeRaiseRegisteredFromStatus(status);
return 0;
});
}
} // namespace tensorflow

View File

@ -49,6 +49,15 @@ inline PyObject* TFStatusToPyExc(const TF_Status* status) {
return CodeToPyExc(TF_GetCode(status));
}
inline pybind11::dict StatusPayloadToDict(const Status& status) {
pybind11::dict dict;
const auto& payloads = status.GetAllPayloads();
for (auto& pair : payloads) {
dict[pair.first.c_str()] = pair.second.c_str();
}
return dict;
}
} // namespace internal
inline void MaybeRaiseFromStatus(const Status& status) {
@ -59,12 +68,17 @@ inline void MaybeRaiseFromStatus(const Status& status) {
}
}
inline void SetRegisteredErrFromStatus(const tensorflow::Status& status) {
PyErr_SetObject(PyExceptionRegistry::Lookup(status.code()),
pybind11::make_tuple(pybind11::none(), pybind11::none(),
status.error_message(),
internal::StatusPayloadToDict(status))
.ptr());
}
inline void MaybeRaiseRegisteredFromStatus(const tensorflow::Status& status) {
if (!status.ok()) {
PyErr_SetObject(PyExceptionRegistry::Lookup(status.code()),
pybind11::make_tuple(pybind11::none(), pybind11::none(),
status.error_message())
.ptr());
SetRegisteredErrFromStatus(status);
throw pybind11::error_already_set();
}
}
@ -74,11 +88,7 @@ inline void MaybeRaiseRegisteredFromStatusWithGIL(
if (!status.ok()) {
// Acquire GIL for throwing exception.
pybind11::gil_scoped_acquire acquire;
PyErr_SetObject(PyExceptionRegistry::Lookup(status.code()),
pybind11::make_tuple(pybind11::none(), pybind11::none(),
status.error_message())
.ptr());
SetRegisteredErrFromStatus(status);
throw pybind11::error_already_set();
}
}

View File

@ -10,6 +10,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -24,6 +28,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -10,6 +10,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -24,6 +28,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=None, keywords=None, defaults=[\'2\'], "
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -10,6 +10,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -24,6 +28,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}

View File

@ -11,6 +11,10 @@ tf_class {
name: "error_code"
mtype: "<type \'property\'>"
}
member {
name: "experimental_payloads"
mtype: "<type \'property\'>"
}
member {
name: "message"
mtype: "<type \'property\'>"
@ -25,6 +29,6 @@ tf_class {
}
member_method {
name: "__init__"
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\', \'error_code\'], varargs=None, keywords=None, defaults=[\'2\'], "
argspec: "args=[\'self\', \'node_def\', \'op\', \'message\'], varargs=args, keywords=None, defaults=None"
}
}