picocli 异常行为改变了吗?

picocli exception behavior changed?

我正在从 picocli 3.9.6 更新到 4.2.0,我 运行 在用新版本替换旧的弃用调用时遇到了问题。

在我的原始版本中,我有这样一个代码块:

try {
    return commandLine.parseWithHandlers(
            new RunLast().useOut(ps),
            new ExceptionHandler(),
            args);
}
catch(Exception e) {
    // handle exceptions
}

ExceptionHandler 处理参数异常和执行异常——两者都被重新抛出,但参数异常将帮助文本添加到异常文本中。在某些情况下,捕获会被击中,例如,命令被赋予了错误的参数。 catch 将确保错误打印在 UI.

我尝试这样更新它:

try {
    commandLine.setOut(pw);
    ExceptionHandler handler = new ExceptionHandler();
    commandLine.setExecutionExceptionHandler(handler);
    commandLine.setParameterExceptionHandler(handler);
    commandLine.execute(args);
    return commandLine.getExecutionResult();
}
catch(Exception e) {
    // handle exceptions
}

在这个新版本中,异常会像以前一样抛出,但它们在被 ExceptionHandler 重新抛出后不再被 catch 块捕获。我怎样才能捕捉到这些异常?

picocli 4.x 中的一个变化是新的 execution framework. The user manual has a section on migration 可能会有用。

根据设计,CommandLine::execute 方法从不抛出异常。所以不需要用 try/catch 块包围对 CommandLine::execute 的调用(除非你需要捕获 ErrorThrowable)。

相反,您可以选择指定自定义异常处理程序,就像您在示例中所做的那样。这些异常处理程序是您可以向用户显示错误消息的地方。 (可能是之前 ExceptionHandler 中的内容和之前 catch 块中的逻辑的组合。)

当用户提供无效输入时调用ParameterExceptionHandler。默认处理程序显示一条错误消息,可能会建议选项或看起来像打字错误的子命令的替代拼写,最后显示使用帮助消息。用户手册的 Handling Errors 部分有一个示例 ShortErrorMessageHandler,当使用帮助消息太长以至于掩盖了错误消息时,它可能很有用。

当业务逻辑抛出异常时调用ExecutionExceptionHandler。默认处理程序只是重新抛出异常,这会导致打印堆栈跟踪。用户手册的 Business Logic Exceptions 部分显示了一个替代方案。

听起来您需要自定义 ExecutionExceptionHandler 来打印堆栈跟踪,然后是使用帮助消息。