I have a setup where I execute jython scripts from a Java application. The java application feed the jython script with variables, coming from the command line, so that a user can write the following code in it's jython script:
print("Hello, %s" % foobar)
And will call the java program with this:
$ java -jar myengine.jar script.py --foobar=baz
Hello, baz
My java application parse the command-line, and create a variable of that name with the given value to give to the jython scripting environment to consume. All is well so far.
My issue is that when the user does not provide the foobar command-line parameter, I'd like to be able to easily provide a fallback in my script. For now, the user needs to write that sort of code to handle the situation where the foobar parameter is missing from the command-line:
try: foobar
except NameError: foobar = "some default value"
But this is cumbersome, especially if the number of parameters is growing. Is there a way to handle that better from the script user point of view?
I was thinking of catching the jython NameError in the Java code, initializing the variable causing the exception to a default value if the variable causing the exception "looks like" a parameter (adding a naming convention is OK), and restarting where the exception occurred. Alternatively, I can require the script user to write code such as this:
parameter(foobar, "some default value")
Or something equivalent.
Well, this is one ugly workaround I found so far. Be careful, as this will call the script in loop many times, and is 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);
}
Related
I am having a problem when trying to use the Z3Str3 from z3-4.8.9-x64-ubuntu-16.04 notably if I substitute the com.microsoft.z3.jar to the one in z3-4.8.8-x64-ubuntu-16.04 I no longer have that issue. The problem is that the Z3 process never comes back with a result, despite the simplicity of the query. I noticed though that it returns the valid answer when I kill my program. I am not noticing that behavior when I am trying to run the same query on the executable, so I am guessing there is something about using the jar file that I might need to tweak one way or the other.
Here is my code. I am using Ubuntu 16.04 LTS, and IntelliJ version ultimate 2020.3.
Many thanks!
import com.microsoft.z3.*;
public class Z3String3Processor_reduced {
public static void main(String[] args) {
StringBuilder currentQuery = new StringBuilder("\n" +
"(declare-const string0 String)\n" +
"(assert (= (str.indexof string0 \"a\" 1) 6))\n" +
"(check-sat)\n" +
"(get-model)\n" +
"\n");
Context context1 = new Context();
Solver solver1 = context1.mkSolver();
Params params = context1.mkParams();
params.add("smt.string_solver", "z3str3");
solver1.setParameters(params);
StringBuilder finalQuery = new StringBuilder(currentQuery.toString());
// attempt to parse the query, if successful continue with checking satisfiability
try {
// throws z3 exception if malformed or unknown constant/operation
BoolExpr[] assertions = context1.parseSMTLIB2String(finalQuery.toString(), null, null, null, null);
solver1.add(assertions);
// check sat, if so we can go ahead and get the model....
if (solver1.check() == Status.SATISFIABLE) {
System.out.println("sat");
} else
System.out.println("not sat");
context1.close();
} catch (Z3Exception e) {
System.out.println("Z3 exception: " + e.getMessage());
}
}
}
I don't think this has anything to do with Java. Let's extract your query and put it in a file named a.smt2:
$ cat a.smt2
(declare-const string0 String)
(assert (= (str.indexof string0 "a" 1) 6))
(check-sat)
(get-model)
Now, if I run:
$ z3 a.smt2
sat
(
(define-fun string0 () String
"FBCADEaGaa")
)
That's good. But if I run:
$ z3 smt.string_solver=z3str3 a.smt2
... does not terminate ..
So, bottom line, your query (as simple as it looks), gives hard time to the z3str3 solver.
I see that you already reported this as a bug at https://github.com/Z3Prover/z3/issues/5673
Given that the default string-solver can handle the query just fine, why not just use that one? If you have to use z3str3 for some other reason, then you've found a case where it doesn't handle this query well; I'm not sure how inclined the z3 folks will be to fix this given the query is handled by the default solver rather quickly. Please report what you find out!
I need to raise a warning during one of my scenario but i don't stop to have this error appearing : "Cannot infer type arguments for Result.Warning<>"
I actually tried to raise the Warning the same way i was raising Failure until now :
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
The custom step i am using it inside is the following : I'm trying to go over a list of Element and checking that the existing value of them is the same or not as the one saved before.
protected void checkXyResourcesValue(Integer xyIterator, List<WebElement> elements, String keyParameter) throws TechnicalException, FailureException {
try {
Integer resIterator = 1;
for(WebElement element : elements) {
String targetKey = "XY" + xyIterator + "RES" + resIterator + keyParameter;
String new_value = element.getAttribute(VALUE) != null ? element.getAttribute(VALUE) : element.getText();
String existing_value = Context.getValue(targetKey) != null ? Context.getValue(targetKey) : targetKey;
if (new_value != existing_value) {
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
}
resIterator++;
}
} catch (Exception e) {
new Result.Failure<>(e.getMessage(), Messages.format(TaroMessages.FAIL_MESSAGE_ACCES_CLIENT_XY_CHECK_RESOURCES_VALUE, keyParameter, xyIterator), true, oscarAccesClientPage.getCallBack());
}
}
For the method to check and saved value I actually inspired myself for the piece of code from NoraUI to save a value on Context or read it from.
I'm using Eclipse Luna 4.4.2 and i try to compile using JDK1.8.0_131.
It may be more related to me not knowing how this work in Java than a real problem so thank you in advance for your help or insights. Don't hesitate to ask if you need more information on the piece of code or the context.
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, 0);
use 0 if you do not use any Model (data serialized) or use id of your Object in the serial.
I'm using Apache Commons CLI 1.3.1 to process some options and some of the options can take one to unlimited number arguments. A trivia example with two options would be like this
usage: myProgram -optionX <arg1> <arg2> <arg3> < ... > [-optionY]
-optionX <arg1> <arg2> <arg3> < ... > optionX takes one to unlimited
number of arguments.
-optionY optionY is optional
What I found is that the second option optionY is always recognized as an ARGUMENT of the optionX instead of being recognized as an OPTION by itself. That means if you type
myProgram -optionX arg1 arg2 -optionY in the command line, you will get three arguments (arg1, arg2, and -optionY) associated with optionX.
Here is the code that anyone can use to reproduce the problem.
import org.apache.commons.cli.*;
public class TestCli {
public static void main(String[] args) {
Option optObj1 = Option.builder("optionX")
.argName("arg1> <arg2> <arg3> < ... ")
.desc("optionX takes one to unlimited number of arguments.")
.required()
.hasArgs()
.build();
Option optObj2 = new Option("optionY", "optionY is optional");
Options optsList = new Options();
optsList.addOption(optObj1);
optsList.addOption(optObj2);
CommandLineParser commandLineParser = new DefaultParser();
try {
CommandLine cmd = commandLineParser.parse(optsList, new String[]{"-optionX", "arg1", "arg2", "-optionY"});
System.out.println("--------------------------");
System.out.println("argument list of optionX: ");
for (String argName : cmd.getOptionValues(optObj1.getOpt())) {
System.out.println("arg: " + argName);
}
System.out.println("--------------------------");
System.out.println("value of optionY: " + cmd.hasOption(optObj2.getOpt()));
} catch (ParseException e) {
System.out.println("Unexcepted option: " + e.getMessage());
}
}
}
This is the output you'll see.
--------------------------
argument list of optionX:
arg: arg1
arg: arg2
arg: -optionY
--------------------------
value of optionY: false
Do I miss something here?
Any suggestion will be really appreciated.
The problem is that you are putting the long name in the short name of the option.
When you use Option optObj1 = Option.builder("optionX").... or new Option("optionY", "optionY is optional"), you're setting the short name of the option, which is supposed to be only 1 character long.
That work well until you have a multi arguments option. In this case, the parser cannot find "o" (the first letter of your option) in his short option list and you don't have a long name set, so the parser determines that -optionY is just another argument for -optionX.
To solve your problem, just set the long option name of your option and it should work alright.
Example
Option.builder("x").longOpt("optionX")....
Option optObj2 = new Option("y", "optionY", hasArgs, "optionY is optional");
This question already has an answer here:
Attempt to index local 'v' (a nil value)
(1 answer)
Closed 5 years ago.
There has been a lot of post about this kind of error and most people say it is related to table and array indexing problems. But I am not using tables at all, I am just trying to call a library function I made and I get this error. Here is the lua script called from java:
String script = new String (
"function event_touch ( )"
+ " pb.open_form ('view_monster');"
+ " print ('I ran the lua script');"
+ "end");
PBLUAengine.run_script(script, "event_touch");
This gives me the following error when trapping the exception:
"function event_touch ( ) pb.open_form ('view_monster'); print ('I ran the lua script');end:1 attempt to index ? (a nil value)"
The run_script() function calls the script like this( I am using luaj):
public static LuaValue run_script ( String script )
{
try
{
LuaValue chunk = s_globals.load( script );
return chunk.call();
}
catch ( Exception e)
{
Gdx.app.error ("PBLUAengine.run_script()", e.getMessage() );
}
return null;
}
The library method goes like this and the same piece of code works when called from java:
static class open_form extends OneArgFunction
{
public LuaValue call (LuaValue formname)
{
String tmpstr = (String ) CoerceLuaToJava.coerce(formname, java.lang.String.class );
try
{
PBscreen_game.hide_subscreen(PBscreen_game.MENU_SUBS);
PBscreen_game.show_subscreen ( PBscreen_game.FORM_SUBS);
PBsubscreen_form.open_form ( new PBform_regular ( tmpstr ) );
}
catch (Exception e)
{
Gdx.app.error("PBLUAlibrary.open_form", e.getMessage());
}
return valueOf ( 0 );
}
}
It basically convert the lua parameter to string, create a new from and pass in parameter the string.
The declaration of the library functions goes like this:
public LuaValue call( LuaValue modname, LuaValue env )
{
LuaValue library = tableOf();
library.set( "open_form", new open_form() );
library.set( "open_system_form", new open_system_form() );
env.set( "pb", library );
return library;
}
Which could be the only "table" I can see in the whole system. This is generally used link the right class with the right function name.
Anybody have an idea?
most people say it is related to table and array indexing problems
It's related to table and array indexing. If you try to index an object and that object is nil, you'll get that error:
I am not using tables at all [..] Here is the lua script:
pb.open_form
pb is being indexed. It's probably nil.
I seems that I solved the problem by adding a require line to include the library. So the new script is:
String script = new String (
"require 'com.lariennalibrary.pixelboard.library.PBLUAlibrary'"
+ "function event_touch ( )"
+ " pb.open_form ('view_monster');"
+ " print ('I ran the next button lua script');"
+ "end");
It ask to include my library class which will add all the "pb.*" functions. I probably deleted the line by error, or managed to make it work somehow without it. Since this library will be required by all script, I might append it by default before each script I try to run.
Thanks Again
I am using Weka to create a classifier via the Java API.
The instances are created using java code.
The classifier is being created from code as well via passing following
String args[]=" -x 10 -s 1 -W weka.classifiers.functions.Logistic".split(" ");
String classname;
String[] tmpOptions = Utils.splitOptions(Utils.getOption("W", args));
classname = tmpOptions[0];
System.out.println(classname);
Classifier cls = (Classifier) Utils.forName(Classifier.class, classname, tmpOptions);
It works fine and does cross validation.
After that I once again load my training instances and label their output as ?
and pass it to classifier using
for (int index = 0; index < postDatas.size(); index++) {
Instance instance = nominal.instance(index);
double label = classifier.classifyInstance(instance);
System.out.println(label);
}
classifier.classifyInstance(instance); gives me following exception:
java.lang.NullPointerException
at weka.classifiers.functions.Logistic.distributionForInstance(Logistic.java:710)
any clues to where am I going wrong?
Since you didn't provide all relevant information, I'll take a shot in the dark:
I'm assuming that you're using Weka version 3.7.5 and I found the following source code for Logistic.java online
public double [] distributionForInstance(Instance instance) throws Exception {
// line 710
m_ReplaceMissingValues.input(instance);
instance = m_ReplaceMissingValues.output();
...
}
Assuming you didn't pass null for instance, this only leaves m_ReplaceMissingValues. That member is initialized when the method Logistic.buildClassifier(Instances train)is called:
public void buildClassifier(Instances train) throws Exception {
...
// missing values
m_ReplaceMissingValues = new ReplaceMissingValues();
m_ReplaceMissingValues.setInputFormat(train);
train = Filter.useFilter(train, m_ReplaceMissingValues);
...
}
It looks like you've never trained your classifier Logistic on any data after you created the object in the line
Classifier cls = (Classifier) Utils.forName(Classifier.class, classname, tmpOptions);