如何用Scopt替代Argot解析HOCON配置适配Spark Submit
从Argot迁移到Scopt解析HOCON配置(最小改动版)
不用担心,Scopt的用法和Argot逻辑非常贴近,咱们几乎可以照搬原来的配置加载逻辑,spark-submit命令完全不用改,甚至后续读取配置的代码都能原封不动保留。
完整迁移代码示例
下面是替换后的main方法代码,我把核心改动点都标清楚了:
import scopt.OptionParser import com.typesafe.config.{Config, ConfigFactory} import java.io.File def main(args: Array[String]) { // 定义一个轻量的case class,用来承载Scopt解析后的命令行参数 case class CliConfig(config: Option[Config] = None) // 初始化Scopt解析器,对应原来Argot的基础设置 val parser = new OptionParser[CliConfig]("generated") { // 替代原来的preUsage,展示应用版本信息 head(generated.Settings.name, generated.Settings.version, generated.Settings.organization) // 解析--config参数,逻辑和原来完全一致 opt[String]("config") .required() // 直接标记为必填,省去手动判断抛异常的步骤 .valueName("<filename>") .action((filename, cfg) => { val file = new File(filename) if (file.exists()) { cfg.copy(config = Some(ConfigFactory.parseFile(file))) } else { failure(s"Configuration file \"$filename\" does not exist") } }) .text("Configuration file.") } // 处理参数解析结果 parser.parse(args, CliConfig()) match { case Some(cliCfg) => // 这里拿到的conf和原来的完全一样,后续读取配置的代码直接复用 val conf = cliCfg.config.get // 原来的业务代码不用动: // conf.getConfig("somelevel").getString("arg1") case None => // 解析失败时Scopt会自动打印用法和错误信息,直接退出即可 sys.exit(1) } }
关键改动说明
- 新增CliConfig case class:Scopt需要一个载体来存储解析后的参数,咱们只需要一个
config字段,非常轻量。 - 解析器初始化:用
scopt.OptionParser替代ArgotParser,head方法对应原来的preUsage,写法更简洁。 - --config参数处理:
- 用
opt[String]("config")定义参数,required()直接标记为必填,省去了原来手动getOrElse抛异常的代码。 - 内部文件检查、ConfigFactory加载的逻辑和原来完全一致,不存在就调用
failure输出错误(Scopt会自动帮咱们打印用法)。
- 用
- 结果处理:用模式匹配替代原来的解析后取值,成功时直接拿到加载好的Config,后续业务逻辑完全不用改。
额外好处
这样改完之后:
- 部署脚本零改动:原来的spark-submit命令
spark/bin/spark-submit --class ConsumerApp --master local[2] some-consumer-jar-0.1.0.jar --config config.hocon可以直接用。 - 业务代码零侵入:原来读取配置的
conf.getConfig("somelevel").getString("arg1")这类代码完全不用调整。 - 错误提示更友好:Scopt自带标准化的参数错误提示,比原来手动抛出异常的体验更好。
内容的提问来源于stack exchange,提问作者Egyptian
相关产品推荐
相关产品推荐

