在Databricks笔记本中管理Scala依赖项

时间:2019-12-06 14:21:04

标签: scala databricks

我是Scala大项目的新开发人员,该项目中的所有代码都存储为笔记本并在Databricks Clusters中运行...

每个笔记本都定义了类和方法,我们有“ Main”笔记本,它们只有很少的代码行,但是在诸如%run ./myPackage/Foo这样的单元格中执行了所有需要的Scala笔记本(即该项目中几乎所有的笔记本)。 。然后这些“主要”笔记本有一个像这样的小Scala代码单元:

import com.bar.foo.Main
Main.main()

此外,每个笔记本均按照Scala的说明import com.bar.foo.MyClass导入所需的包。

我觉得这很烦人:

  • 如果我移动一个笔记本,则必须更新所有主要笔记本/测试笔记本中的所有%run path/Notebook命令
  • 我觉得在主笔记本中运行笔记本并将软件包导入所有其他笔记本中是多余的。

您知道另一个工作流程吗?有没有更简单的方法可以在Databricks中使用多个Scala笔记本?

1 个答案:

答案 0 :(得分:1)

我认为,当用户和公司将笔记本视为软件工程原理的替代品时,就会发生这些问题。为了解决这些问题而创建的软件世界广泛使用了design patterns,很难(如果不是不可能)将它们应用于笔记本电脑。因此,我认为用户不应将笔记本作为开发最终用户解决方案的工具。笔记本电脑的主要作用曾经是原型 ML测试,因此从定义上讲,它们不适用于模块化和可扩展性是重要因素的情况。

对于您的情况,并假设不可避免地要使用笔记本,我建议尽量减少笔记本的使用,并开始将代码组织到JAR库中。如果笔记本之间共享大部分代码,这将很有用。

例如,考虑笔记本N1N2都使用笔记本N3N4的情况。然后,您可以将N3N4的实现放入一个JAR,将其称为common_lib.jar,然后使common_lib.jarN1和{{1 }}(将其附加到它们运行所在的集群上)(假设您运行的是notebook job)。通过遵循这种方法,您可以实现:

  • 更好的模块化,因为您完全分离了笔记本的功能。同样,对于每个作业/笔记本,您都可以将确切的依赖项附加到群集,避免由于难以将笔记本应用程序划分为模块而出现冗余的依赖项。

  • 更多可维护的代码。最终,每个模块都应该有一个最终的笔记本,用于导入依赖项,就像在普通的scala应用程序中那样,避免了调用多个笔记本所需的复杂层次结构。

  • 更多可扩展的代码。笔记本电脑提供的接口N2较差,并且dbutils.widget.text(...)绝对比使用scala / java所能实现的要少得多。

  • 更多可测试的代码。您现在应该知道,使用笔记本很难实施正确的单元或集成测试。通过将主要实现放入jar中,您可以像使用任何scala / java应用程序一样执行单元测试。

更新

针对您的情况的一种解决方案(无法重构到JAR库)是将笔记本组织成模块,其中每个笔记本将使用负责模块所有依赖项的 _includes _ 文件。 _includes _ 文件看起来像是下一个代码段:

dbutils.widget.get(...)

现在,假设笔记本X1和X2共享相同的依赖项%run "myproject/lib/notebook_1" %run "myproject/lib/notebook_3" ... myproject/lib/notebook_1,以便使用上述依赖项,您只需将 _includes _ 文件放在相同的文件夹并执行:

myproject/lib/notebook_3

在X1和/或X2笔记本的第一个单元格中。这样,您就有一种通用的方式来包含项目的所有依赖项,并且避免了需要重复复制/粘贴所有包含项的情况。

尽管这可能是一项重大改进,但它没有提供一种自动的方法来检查并在项目中包括依赖项的正确路径。顺便说一句,我不知道这种自动浏览文件和动态更改导入的方式。但是,一种方法是编写外部自定义脚本。尽管此脚本不应该在您的工作中调用。

注意:您必须确保正确定义了依赖项的层次结构,并且没有任何循环依赖项。