提交 cefc5553 authored 作者: David Warde-Farley's avatar David Warde-Farley

Remove annoying raise_with_op behaviour, document.

This adds a docstring for raise_with_op and also modifies its behaviour somewhat. Previously, the exception was re-raised with a different 'args' member -- namely, in addition to the exception message it added two new elements to the tuple: the Op itself and a string telling you where in the graph the corresponding Apply node appeared. This gets in the way if you want to have an exception message containing formatting (newlines and tabs), since the entire tuple is printed, and the formatting on the string is not rendered. I've never seen the Apply node index be of use to anyone debugging, but my proposed solution is to stash that information in __op_instance__ and __applynode_index__ on the object instead of in the args tuple. I would not be against appending to args[0], the exception message, with applynode information, but this is easy enough to obtain at the pdb prompt with my modifications.
上级 344af686
...@@ -33,8 +33,37 @@ def thunk_hook(type, value, trace): ...@@ -33,8 +33,37 @@ def thunk_hook(type, value, trace):
sys.excepthook = thunk_hook sys.excepthook = thunk_hook
def raise_with_op(op, exc_info = None): def raise_with_op(op, exc_info=None):
"""WRITEME""" """
Re-raise an exception while annotating the exception object with
debug info.
Parameters
----------
op : object
The Op object that resulted in the raised exception.
exc_info : tuple, optional
A tuple containing the exception type, exception object and
associated traceback, as would be returned by a call to
`sys.exc_info()` (which is done if `None` is passed).
Notes
-----
This re-raises the exception described by `exc_info` (or the last
one raised, if `exc_info` is omitted) and annotates the exception
object with several new members which may be helpful for debugging
Theano graphs. They are:
* __op_instance__: The Op that is responsible for the exception
being raised.
* __thunk_trace__: A traceback corresponding to the code that
actually generated the exception, if it is available.
* __applynode_index__: The index of the Apply node corresponding
to this op in `op.env.toposort()`.
The exception is not annotated if it is of type `KeyboardInterrupt`.
"""
if exc_info is None: if exc_info is None:
exc_info = sys.exc_info() exc_info = sys.exc_info()
exc_type, exc_value, exc_trace = exc_info exc_type, exc_value, exc_trace = exc_info
...@@ -46,9 +75,11 @@ def raise_with_op(op, exc_info = None): ...@@ -46,9 +75,11 @@ def raise_with_op(op, exc_info = None):
except AttributeError: except AttributeError:
trace = () trace = ()
exc_value.__thunk_trace__ = trace exc_value.__thunk_trace__ = trace
exc_value.args += (op, ) exc_value.__op_instance__ = op
if op in op.env.toposort(): if op in op.env.toposort():
exc_value.args += ('Sequence id of Apply node='+str(op.env.toposort().index(op)),) exc_value.__applynode_index__ = op.env.toposort().index(op)
else:
exc_value.__applynode_index__ = None
raise exc_type, exc_value, exc_trace raise exc_type, exc_value, exc_trace
...@@ -283,7 +314,7 @@ def streamline(env, thunks, order, post_thunk_old_storage = None, no_recycling = ...@@ -283,7 +314,7 @@ def streamline(env, thunks, order, post_thunk_old_storage = None, no_recycling =
thunk() thunk()
for old_s in old_storage: for old_s in old_storage:
old_s[0] = None old_s[0] = None
except Exception: except:
raise_with_op(node) raise_with_op(node)
f = streamline_default_f f = streamline_default_f
elif nice_errors: elif nice_errors:
...@@ -294,7 +325,7 @@ def streamline(env, thunks, order, post_thunk_old_storage = None, no_recycling = ...@@ -294,7 +325,7 @@ def streamline(env, thunks, order, post_thunk_old_storage = None, no_recycling =
try: try:
for thunk, node in thunk_node_list: for thunk, node in thunk_node_list:
thunk() thunk()
except Exception: except:
raise_with_op(node) raise_with_op(node)
f = streamline_nice_errors_f f = streamline_nice_errors_f
else: else:
...@@ -554,7 +585,7 @@ class WrapLinker(Linker): ...@@ -554,7 +585,7 @@ class WrapLinker(Linker):
for i, (thunks, node) in enumerate(zip(thunk_groups, order)): for i, (thunks, node) in enumerate(zip(thunk_groups, order)):
try: try:
wrapper(i, node, *thunks) wrapper(i, node, *thunks)
except Exception: except:
raise_with_op(node) raise_with_op(node)
f.thunk_groups = thunk_groups f.thunk_groups = thunk_groups
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论