我有一个设置,可以从Java应用程序执行jython脚本。 Java应用程序向jython脚本提供了来自命令行的变量,以便用户可以在其jython脚本中编写以下代码:
print("Hello, %s" % foobar)
并且将以此来调用Java程序:
$ java -jar myengine.jar script.py --foobar=baz
Hello, baz
我的Java应用程序解析命令行,并使用给定的值创建该名称的变量,以提供给jython脚本环境使用。到目前为止一切都很好。
我的问题是,当用户不提供foobar
命令行参数时,我希望能够轻松地在脚本中提供后备。现在,用户需要编写这种代码来处理命令行中缺少foobar
参数的情况:
try: foobar
except NameError: foobar = "some default value"
但这很麻烦,尤其是在参数数量不断增长的情况下。 是否有一种方法可以从脚本用户的角度更好地处理此问题?
我曾想在Java代码中捕获jython NameError,如果导致异常的变量“看起来像”参数,则将导致异常的变量初始化为默认值(添加命名约定就可以了,然后在发生异常。或者,我可以要求脚本用户编写如下代码:
parameter(foobar, "some default value")
或等效的东西。
嗯,这是我到目前为止发现的一个丑陋的解决方法。 请小心,因为这将多次循环调用脚本,并且为O(n ^ 2)。
private void callScriptLoop(String scriptfile) {
PythonInterpreter pi = new PythonInterpreter();
pi.set("env", someEnv);
int nloop = 0;
boolean shouldRestart;
do {
shouldRestart = false;
try {
pi.execfile(scriptfile);
} catch (Throwable e) {
if (e instanceof PyException) {
PyException pe = (PyException) e;
String typ = pe.type.toString();
String val = pe.value.toString();
Matcher m = Pattern.compile("^name '(.*)' is not defined")
.matcher(val);
if (typ.equals("<type 'exceptions.NameError'>")
&& m.find()) {
String varname = m.group(1);
pi.set(varname, Py.None);
System.out.println(
"Initializing missing parameter '"
+ varname + "' to default value (None).");
shouldRestart = true;
nloop++;
if (nloop > 100)
throw new RuntimeException(
"NameError handler infinite loop detected: bailing-out.");
}
}
if (!shouldRestart)
throw e;
}
} while (shouldRestart);
}