提交 4428570f authored 作者: Frederic Bastien's avatar Frederic Bastien

Make MissingInputError always print the trace where the input was created.

上级 acdaf1d7
......@@ -49,8 +49,18 @@ class MissingInputError(Exception):
A symbolic input needed to compute the outputs is missing.
"""
pass
def __init__(self, *args, **kwargs):
if kwargs:
assert kwargs.keys() == ["variable"]
tr = getattr(kwargs.values()[0].tag, 'trace', [])
if type(tr) is list and len(tr) > 0:
sio = StringIO()
print("\nBacktrace when the variable is created:", file=sio)
for subtr in kwargs.values()[0].tag.trace:
traceback.print_list(subtr, sio)
args = args + (str(sio.getvalue()),)
s = '\n'.join(args) # Needed to have the new line print correctly
Exception.__init__(self, s)
class FunctionGraph(utils.object2):
......@@ -364,7 +374,7 @@ class FunctionGraph(utils.object2):
if isinstance(variable.type, NullType):
raise TypeError("Computation graph contains a NaN. " +
variable.type.why_null)
raise MissingInputError("Undeclared input", variable)
raise MissingInputError("Undeclared input", variable=variable)
if not getattr(variable, 'fgraph', None) is self:
self.__setup_r__(variable)
self.variables.add(variable)
......@@ -392,78 +402,6 @@ class FunctionGraph(utils.object2):
if (r.owner is None and
not isinstance(r, graph.Constant) and
r not in self.inputs):
# Verbose error message
# Show a complete chain of variables from the missing input to an output
if config.exception_verbosity == 'high':
def find_path_to(output_var, input_var):
"""
Returns a list of each variable on a (not
necessarily unique) path from input_var to
output_var, where each variable in the list has
the preceding variable as one of its inputs.
Returns None if no path exists.
"""
# If output and input are the same we have a singleton path
if output_var is input_var:
return [output_var]
# If output has no inputs then there is no path
owner = output_var.owner
if owner is None:
return None
# If input_var is an input to the output node, there is a
# simple two element path
inputs = owner.inputs
if input_var in inputs:
return [input_var, output_var]
# Otherwise we must recurse by searching for a path to one
# of our inputs, then appending the output to that path
for ipt in inputs:
path = find_path_to(ipt, input_var)
if path is not None:
path.append(output_var)
return path
# Since none of the above methods returned a path, there is none
return None
# Try different outputs until we find one that has a path to the missing input
for output in self.outputs:
path = find_path_to(output, r)
if path is not None:
break
# if there is no path then r isn't really a graph input so we shouldn't be running error
# handler code in the first place
assert path is not None
tr = getattr(r.tag, 'trace', [])
detailed_err_msg = ""
if type(tr) is list and len(tr) > 0:
detailed_err_msg += "\nBacktrace when the variable is created:\n"
# Print separate message for each element in
# the list of batcktraces
sio = StringIO()
for subtr in tr:
traceback.print_list(subtr, sio)
detailed_err_msg += str(sio.getvalue())
raise MissingInputError(
'A variable that is an input to the graph was '
'neither provided as an input to the function '
'nor given a value. A chain of variables '
'leading from this input to an output is %s. '
'This chain may not be unique' % str(path) +
detailed_err_msg)
# Standard error message
raise MissingInputError((
"An input of the graph, used to compute %s, "
......@@ -471,7 +409,7 @@ class FunctionGraph(utils.object2):
"Use the Theano flag exception_verbosity='high',"
"for more information on this error."
% str(node)),
r)
variable=r)
for node in new_nodes:
assert node not in self.apply_nodes
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论