说我在达格斯特中有两个固体连接在管道上。第一个实体可能会执行某些处理并生成有效输入,以便其余管道执行,或者生成不应进一步处理的无效输入。为了获得此结果,当数据满足无效条件时,我将引发错误,因此管道将停止,并且将跳过其余实体。
引发错误以解决用例似乎很棘手,有没有办法我可以不使用异常而跳过其余管道的执行?
from dagster import solid, pipeline
@solid
def solid_1(context, x: int):
y = x + 1
if y%2 == 0:
raise "No even number is further processed"
return y
@solid
def solid_2(context, y:int):
return y**2
@pipeline
def toy_pipeline():
solid_2(solid_1())
在这个非常人为的示例中,仅当第一个实体的输出为奇数时才应执行实体2。
在我的实际用例中,第一个实体轮询数据库,有时找不到任何要处理的数据。在这种情况下,不要将执行标记为失败,而应将其标记为成功。可以在每个下游实体中检查数据是否满足条件,但这很快增加了样板。当接收数据的实体找不到要处理的数据时,最好有一种方法跳过所有下游实体的执行。
答案 0 :(得分:2)
要实现所需的行为,可以使用相应is_required=False
上的OutputDefinition
参数将输出标记为可选。这意味着固体不必一定要产生产量。
如果没有产生可选的输出,则依赖于该输出的所有下游固体将简单地跳过。这对于使管道短路(这是用例)或更复杂的分支逻辑都很有用。跳过实体时,管道运行不会标记为失败。
您正在使用类型提示定义输入和输出类型,但是由于需要指定is_required
参数,因此需要使用显式的OuputDefinition
。
from dagster import pipeline, solid, RepositoryDefinition, InputDefinition, OutputDefinition, Output
from typing import List
def query_db():
return []
@solid(output_defs=[OutputDefinition(List[int], 'data', is_required=False)])
def solid_1(context):
rows = query_db()
if len(rows) > 0:
yield Output(rows, output_name="data")
@solid
def solid_2(context, data: List[int]):
context.log.info(str(data))
pass
@pipeline
def my_pipeline():
solid_2(solid_1())
也可以使用solid_2
而不是类型提示来定义实体InputDefinition
。类型提示是InputDefinitions
的语法糖:
@solid(input_defs=[InputDefinition('data', List[int])])
def solid_2(context, data):
context.log.info(str(data))
# Process data
pass
作为旁注:通常,异常是将实体标记为失败的正确方法,并且在Dagster代码中不认为异常。