PythonInterpreter exec function return empty output stream - java

I'm using org.python.util.PythonInterpreter class to execute python code in java. Please find below the snippet of of my code.
PythonInterpreter pythonInterpreter = new PythonInterpreter(null, new PySystemState());
ByteArrayOutputStream outStream = new ByteArrayOutputStream(16384);
pythonInterpreter.setOut(outStream);
pythonInterpreter.setErr(outStream);
// execute the code
pythonInterpreter.exec(script);
String consoleOutput = outStream.toString();
outStream.flush();
System.out.println("Console output :- "+consoleOutput);
The problem with the above code is for the same script sometimes I get 'consoleOutput' empty. I'm not able to figure out the problem. For running the above code 1000 times, at least 4 times I get empty output.
On the other hand if I use the default constructor as shown below it works just fine
PythonInterpreter pythonInterpreter = new PythonInterpreter();

Digging more into the problem I found, setting the property python.site.import to false triggers this problem. This issue occurs in Jython standalone version 2.7.0. Updating to the June 2017 release of the standalone jar(2.7.1) fixes this issue.

Related

Is there a way to have Java call a bash script which calls javac and java?

I'm trying to train a neural network to play Halite 3. The provided interface is a bash script which:
1. compiles my bot
2. calls the binary file with a string to run the bot java myBot
I'm trying to run this script from Java to train the network.
I've tried using a ProcessBuilder to run the script as well as the binary in the script. Running the script produces no output, and using echo I've determined that the program terminates when javac is called in the script. Removing that call, it terminates when the program is run.
I've tried calling the program directly as well using ProcessBuilder, and this does indeed produce output. The issue is it doesn't run the bots properly saying it can't find the file. I've tried changing the path to be relative to different directory levels as well as the absolute path (the java command doesn't seem to like absolute paths?).
Calling the binary directly:
List<String> cmd = new ArrayList<>();
cmd.add(dir+ "/src/halite");
// Replay
cmd.add("--replay-directory");
cmd.add(dir+"/replays/");
// Options
cmd.add("--results-as-json");
cmd.add("--no-logs");
// Dimensions
cmd.add("--width");
cmd.add("16");
cmd.add("--height");
cmd.add("16");
// Players
cmd.add("\"java -cp . myBot\"");
cmd.add("\"java -cp . myBot\"");
Process proc = new ProcessBuilder(cmd).start();
InputStream is = proc.getInputStream();
Scanner s = new Scanner(is);
while (s.hasNext()){
System.out.println((String) s.next());
}
This code does produce a JSON, however, I get an error in my logs saying that the bots do not run.

python's print causing errors in ProcessBuilder Java

I'm trying to use ProcessBuilder in Java to run some python code. print is causing errors but print() works fine.
The java code is:
List<String> list = Arrays.asList("python", "C:/.../test.py");
ProcessBuilder pb = new ProcessBuilder(list);
Process process = pb.start();
It generates a file if test.py is this
open('C:/.../outputtest2.txt', 'a')
print(5)
but it doesnt't work if test.py is this
open('C:/.../outputtest2.txt', 'a')
print 5
Both work fine if I run the script from the command line. I've tried changing and even removing Python 3 from the PATH but still getting the error. I can't find any similar errors online.
This is a python syntax error. As you know in python 3 you have to put parentheses for print function. for some reasons ( e.g. system cache) your ProcessBuilder use python 3 for running your python code.
This problem should solve by restarting the computer but if it doesn't work, you can run it manually with python 2.x
For example :
List<String> list = Arrays.asList("C:/python27/python.exe", "C:/.../test.py");
ProcessBuilder pb = new ProcessBuilder(list);

Executing shell-script with parameters using apache.commons.exec in Windows

I am trying to run a script using apache-commons-exec which was implemented using the java approximation to run. This script is executed in the production server (Linux) but I need to test it in my localhost to see that everything works OK.
Here is my code to launch cygwin and this code is working in the cmd.exe but it does not work when I try to launch it using commons.exec:
OutputStream outputStream = new ByteArrayOutputStream();
DefaultExecutor exec = new DefaultExecutor();
exec.setWatchdog(new ExecuteWatchdog(1000));
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
exec.setStreamHandler(streamHandler);
CommandLine cmdLine = CommandLine.parse("C:\\cygwin64\\bin\\bash");
cmdLine.addArgument("-c");
cmdLine.addArgument("/cygdrive/c/dev/launch.sh");
int exit = exec.execute(cmdLine);
logger.warn("Job exit: " + exit);
It returns 1 and no output or log error:
org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
Is there anything missing? How can I catch the output properly?
A bit of a guess this but might help.
Sometimes an exit code = 1 represents "success". However, Apache Commons Exec by default interprets an exit code = 1 as a failure and will throw an ExecuteException if the script in question exits with and exit code = 1.
You can tell your DefaultExecutor that "exit code = 1 = success" using the following code:
exec.setExitValue(1);
Might not be the reason but worth a go.

Python Interpreter in Jython

All I'm trying to do is pass an argument to the python interpreter so it can be passed as an argument for a module.
E.g. I have the following defined in a py file:
def print_twice(test):
print test
print test
I want to pass it the argument "Adam", so I've tried:
// Create an instance of the PythonInterpreter
PythonInterpreter interp = new PythonInterpreter();
// The exec() method executes strings of code
interp.exec("import sys");
interp.exec("print sys");
PyCode pyTest = interp.compile("Adam", "C:/Users/Adam/workspace/JythonTest/printTwice.py");
System.out.println(pyTest.toString());
I've also tried:
interp.eval("print_twice('Adam')");
I've been using the following Jython API but I don't understand it well:
http://www.jython.org/javadoc/org/python/util/PythonInterpreter.html#compile%28java.lang.String,%20java.lang.String%29
I would be very grateful for your advices.
Thank you
This should work:
interp.exec("import YOUR_PYTHON_FILE.py");
interp.exec("YOUR_PYTHON_FILE.print_twice('Adam')");
Its equivalent in a python console is this:
>>> import YOUR_PYTHON_FILE.py
>>> YOUR_PYTHON_FILE.print_twice('Adam')
Adam
Adam
You shouldn't need to explicitly compile the script, just import it and the interpreter will take care of compilation. Something like this (assuming printTwice.py is in the working directory of your program:
interp.exec("from printTwice import print_twice");
interp.exec("print_twice('Adam')");
You don't need to use interp.eval on the second line assuming that print_twice does actually contain print statements; if it just returns a string then you probably want
System.out.println(interp.eval("print_twice('Adam')"));.

Calling Python script from JAVA MySQLdb imports

I am calling a Python script from my Java code. This is the code :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class JavaRunCommand {
public static void main(String args[]) throws IOException {
// set up the command and parameter
String pythonScriptPath = "my-path";
String[] cmd = new String[2];
cmd[0] = "python2.6";
cmd[1] = pythonScriptPath;
// create runtime to execute external command
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(cmd);
// retrieve output from python script
BufferedReader bfr = new BufferedReader(new InputStreamReader(
pr.getInputStream()));
String line = "";
while ((line = bfr.readLine()) != null) {
// display each output line form python script
System.out.println(line);
}
}
}
python.py which works
import os
from stat import *
c = 5
print c
python.py which does not works
import MySQLdb
import os
from stat import *
c = 5
print c
# some database code down
So, I am at a critical stage where I have a deadline for my startup and I have to show my MVP project to the client and I was thinking of calling Python script like this. It works when I am printing anything without dB connection and MySQLdb library. But when I include them, it does not run the python script. Whats wrong here. Isnt it suppose to run the process handling all the inputs. I have MySQLdb installed and the script runs without the java code.
I know this is not the best way to solve the issue. But to show something to the client I need this thing working. Any suggestions ?
So, I discovered that the issue was with the arguments that I was passing in Java to run the python program.
The first argument was - python 2.6 but it should have rather been just python not some version number because there was compatibility issue with MySQLdB and python.
I finally decided to use MySQL Python connector instead of MySQLdB in python code. It worked like charm and the problems got solved !

Categories