不太一样,但我的回答 here 可能有用。
我建议在您的情况下,最简单的方法确实是定义两个目录条目并将 Kedro 保存到这两个条目(并从本地加载以提高速度),这为您提供了最大的灵活性,尽管我承认不是最漂亮的。
就避免所有需要返回两个值的节点函数而言,我建议将装饰器应用于您使用特定标签标记的某些节点,例如 tags=["s3_replica"] 从以下脚本中获取灵感(从同事那里窃取我的):
class S3DataReplicationHook:
"""
Hook to replicate the output of any node tagged with `s3_replica` to S3.
E.g. if a node is defined as:
node(
func=myfunction,
inputs=['ds1', 'ds2'],
outputs=['ds3', 'ds4'],
tags=['tag1', 's3_replica']
)
Then the hook will expect to see `ds3.s3` and `ds4.s3` in the catalog.
"""
@hook_impl
def before_node_run(
self,
node: Node,
catalog: DataCatalog,
inputs: Dict[str, Any],
is_async: bool,
run_id: str,
) -> None:
if "s3_replica" in node.tags:
node.func = _duplicate_outputs(node.func)
node.outputs = _add_local_s3_outputs(node.outputs)
def _duplicate_outputs(func: Callable) -> Callable:
def wrapped(*args, **kwargs):
outputs = func(*args, **kwargs)
return (outputs,) + (outputs,)
return wrapped
def _add_local_s3_outputs(outputs: List[str]) -> List[str]:
return outputs + [f'{o}.s3' for o in outputs]
上面是一个钩子,所以你可以把它放在你项目中的hooks.py文件(或任何你想要的地方)中,然后将它导入你的settings.py文件并放入:
from .hooks import ProjectHooks, S3DataReplicationHook
hooks = (ProjectHooks(), S3DataReplicatonHook())
在你的settings.py。
您可以稍微巧妙地使用输出命名约定,使其仅复制某些输出(例如,也许您同意所有以 .local 结尾的目录条目也必须具有相应的 .s3 条目并且您进行了变异你的node 的outputs 相应地在那个钩子中,而不是对每个输出都这样做。
如果您想更聪明一点,您可以使用 after_catalog_created 挂钩将相应的 S3 条目注入目录,而不是再次按照您的命名约定在目录中手动编写数据集的 S3 版本选择。虽然我认为从长远来看,编写 S3 条目更具可读性。