Kaushik Visvanathan
07/22/2020, 7:02 PMOutputdefinition(Optional[float], is_required=False
) based on a condition. As i understand it - if the condition fails, all downstream solids dependent on this solids input are skipped and the pipeline runs to completion. The issue arises when calling the output_values
on the enclosing composite's execution result - it seems to throw an error complaining that output does not exist for some of these conditional solids, even if the outputs are marked as optional. Is this expected behavior? The outputs of the composite are marked as optional tooalex
07/22/2020, 7:03 PMoutput_values
- can you share some more detail such as the full error outputKaushik Visvanathan
07/22/2020, 8:01 PM@solid(
output_defs=[
OutputDefinition(Optional[float], name="foo_output", is_required=False),
]
)
def foo_solid(
context,
condition,
):
if condition:
yield Output(1.0, 'foo_output')
@composite_solid(
output_defs=[
OutputDefinition(Optional[float], name="foo_output", is_required=False),
]
)
def foo_composite():
foo = foo_solid()
return {"foo_output": foo}
result = execute_solid(foo_composite) # simplified to exclude mode and env dict which we have built
result.output_values # error is here
Exception :
dagster/core/execution/results.py in output_values(self)
256 return {
257 output_name: self.output_value(output_name)
--> 258 for output_name in self.solid.definition.output_dict
259 }
260
dagster/core/execution/results.py in <dictcomp>(.0)
256 return {
257 output_name: self.output_value(output_name)
--> 258 for output_name in self.solid.definition.output_dict
259 }
260
dagster/core/execution/results.py in output_value(self, output_name)
283 self.solid.definition.solid_named(output_mapping.solid_name),
284 '.'.join([self.handle, output_mapping.solid_name]),
--> 285 ).output_value(output_mapping.output_name)
286
287
dagster/core/execution/results.py in output_value(self, output_name)
496 'Did not find result {output_name} in solid {self.solid.name} '
497 'execution result'
--> 498 ).format(output_name=output_name, self=self)
499 )
500 else:
DagsterInvariantViolationError: Did not find result foo_output in solid foo_solid execution result
SolidExecutionResult
class's output_value
method to see if a given output is required or not. Is this something I could make a PR for? Would that be the fastest way to resolve this issue?alex
07/23/2020, 6:45 PMKaushik Visvanathan
07/23/2020, 7:21 PM@property
def output_values(self):
values = {}
for output_name in self.solid.definition.output_dict:
output_mapping = self.solid.definition.get_output_mapping(output_name)
inner_solid_values = self._result_for_handle(
self.solid.definition.solid_named(output_mapping.solid_name),
SolidHandle(output_mapping.solid_name, None),
).output_values
if output_mapping.output_name in inner_solid_values: # This line
values[output_name] = inner_solid_values[output_mapping.output_name]
Shouldn't there be a check to make sure inner_solid_values
is not None
before it starts iterating?dagster/core/execution/results.py in output_values(self)
215 ).output_values
216
--> 217 if output_mapping.output_name in inner_solid_values:
218 values[output_name] = inner_solid_values[output_mapping.output_name]
219
TypeError: argument of type 'NoneType' is not iterable
Jamie
07/28/2020, 7:41 PM@solid(
output_defs=[
OutputDefinition(Int, name='result', is_required=False),
]
)
def optional_run(context, should_run: Bool):
if should_run:
yield Output(1, 'result')
@solid(
output_defs=[
OutputDefinition(Bool, name='result', is_required=False),
]
)
def dependent_solid(context, x: Int):
yield Output(x == 1, 'result')
@composite_solid(
output_defs=[
OutputDefinition(Bool, name='result', is_required=False)
]
)
def optional_outputs_composite(should_run: Bool):
res = dependent_solid(optional_run(should_run))
return {
'result': res
}
result = execute_solid(optional_outputs_composite(False))
result.output_values
alex
07/28/2020, 7:44 PM0.8.9
?Jamie
07/28/2020, 7:45 PMalex
07/28/2020, 7:49 PM