My problem is somewhat similar to this question.
I try to communicate from Python with a Jython program (that needs to keep running because it communicates with a Java API).
However, i can't get the output in realtime, whatever i try:
p2=Popen([path_jython],stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
p2.stdin.write('test="hallo"\n')
p2.stdin.write('print test\n')
p2.stdin.flush()
for line in p2.stdout:
print line
Nothing happens, the program blocks. It doesn't change when i iterate over p2.stdout.readlines() or iter(md5.stdout.readline, '') or when I repeatedly call p2.stdout.read(1) like suggested in the linked question.
If i add print p2.communicate() after the flush() however, i get the desired output:
>>> ('hallo\r\n', '\r\n')
but the program terminates afterwards...
Does anyone have a solution for this problem? Or are there alternatives to communicate effectively with a running Jython process? Happy for any advice!
EDIT: Python 2.7.5, Jython 2.7.1b
try to make jython stdout/stderr unbuffered, pass -u command-line argument
if you set stderr=PIPE then you should read it, otherwise a deadlock may occur if the child process fills the OS pipe buffer corresponding to its stderr. You could redirect it to stdout: stderr=STDOUT
set Python side buffering explicitely: bufsize=1 (line-buffered)
use iter(p.stdout.readline, '') to avoid read-ahead bug on Python 2
from subprocess import Popen, PIPE, STDOUT
p = Popen(['jython', '-u', ...], stdin=PIPE, stdout=PIPE, stderr=STDOUT,
bufsize=1)
print >>p.stdin, 'test="hallo"' #NOTE: it uses `os.linesep`
print >>p.stdin, 'print test'
p.stdin.close() # + implicit .flush()
for line in iter(p.stdout.readline, ''):
print line, #NOTE: comma -- softspace hack to avoid duplicate newlines
p.stdout.close()
rc = p.wait()
Related
I'm writing an application in Java that uses the following external library: SCPSolver (link: http://scpsolver.org/).
The library appears to be a wrapper for a c library and prints some information on the standard out. My problem is I'd like my application to have a clean output: I'm looking for a way to either
a. clear the console, which might be either a system (windows) console or eclipse's console; or
b. straight up prevent the library from printing on the output.
Regarding point a:
I've tried both using
Runtime.getRuntime().exec("cls");
and
System.out.print("\033[H\033[2J");
and neither work.
I've tried printing "\b" characters but to no avail. In all these cases, I get gibberish in the output.
Regarding point b:
I've tried redirecting System.out to a new PrintStream, but it doesn't work. That's most likely because the library is a wrapper to a c library, and the c library prints bypass java's System.out. Thus I'm not really sure this approach would work, as I have no control over what the library does. I've looked in the documentation for a way to disable the output, and haven't found anything useful yet.
A possibly useful note:
Calling
System.out.close();
before asking the solver to solve an LP problem prevents the output from being displayed. Of course, the problem then is: I have no more stream to stdout to print to. Maybe a solution could be getting another stream to the same console? Though I have no idea how to do this.
In short:
The call to lpw.solve() is what prints the undesired output:
LPWizard lpw = new LPWizard();
// ...
LPSolution solution = lpw.solve();
Current output is:
GLPK Simplex Optimizer, v4.65 4 rows, 4 columns, 8 non-zeros
0: obj = 0.000000000e+000 inf = 2.700e+001 (4)
3: obj = 1.350000000e+001 inf = 0.000e+000 (0) OPTIMAL LP SOLUTION FOUND x1: 4.0 x2: 2.5 x3: 7.0 x4: 0.0
I'd expect it to instead be none.
I want to read python dictionary string using java. Example string:
{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}
This is not a valid JSON. I want it to convert into proper JSON using java code.
well, the best way would be to pass it through a python script that reads that data and outputs valid json:
>>> json.dumps(ast.literal_eval("{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}"))
'{"name": "Shivam", "otherInfo": [[0], [1]], "isMale": true}'
so you could create a script that only contains:
import json, ast; print(json.dumps(ast.literal_eval(sys.argv[1])))
then you can make it a python oneliner like so:
python -c "import sys, ast, json ; print(json.dumps(ast.literal_eval(sys.argv[1])))" "{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}"
that you can run from your shell, meaning you can run it from within java the same way:
String PythonData = "{'name': u'Shivam', 'otherInfo': [[0], [1]], 'isMale': True}";
String[] cmd = {
"python", "-c", "import sys, ast, json ; print(json.dumps(ast.literal_eval(sys.argv[1])))",
python_data
};
Runtime.getRuntime().exec(cmd);
and as output you'll have a proper JSON string.
This solution is the most reliable way I can think of, as it's going to parse safely any python syntax without issue (as it's using the python parser to do so), without opening a window for code injection.
But I wouldn't recommend using it, because you'd be spawning a python process for each string you parse, which would be a performance killer.
As an improvement on top of that first answer, you could use some jython to run that python code in the JVM for a bit more performance.
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.eval("to_json = lambda d: json.dumps(ast.literal_eval(d))")
PyObject ToJson = interpreter.get("to_json");
PyObject result = ToJson.__call__(new PyString(PythonData));
String realResult = (String) result.__tojava__(String.class);
The above is untested (so it's likely to fail and spawn dragons 👹) and I'm pretty sure you can make it more elegant. It's loosely adapted from this answer. I'll leave up to you as an exercise to see how you can include the jython environment in your Java runtime ☺.
P.S.: Another solution would be to try and fix every pattern you can think of using a gigantic regexp or multiple ones. But even if on simpler cases that might work, I would advise against that, because regex is the wrong tool for the job, as it won't be expressive enough and you'll never be comprehensive. It's only a good way to plant a seed for a bug that'll kill you at some point in the future.
P.S.2: Whenever you need to parse code from an external source, always make sure that data is sanitized and safe. Never forget about little bobby tables
In conjunction to the other answer: it is straight forward to simply invoke that python one-liner statement to "translate" a python-dict-string into a standard JSON string.
But doing a new Process for each row in your database might turn into a performance killer quickly.
Thus there are two options that you should consider on top of that:
establish some small "python server" that keeps running; its only job is to do that translation for JVMs that can connect to it
you can look into jython. Meaning: simply enable your JVM to run python code. In other words: instead of writing your own python-dict-string parser; you simply add "python powers" to your JVM; and rely on existing components to that translation for you.
I am reading through the java tutorials, and I don't understand when it says
"The following is the output from the program when you use 4.5 and 87.2 for the command-line arguments:"
What I mean is how do I pass the values to the program. A piece of the code is this.
float a = (Float.valueOf(args[0])).floatValue();
float b = (Float.valueOf(args[1])).floatValue();
I have tried changing "args[0]" to "4.5" and "args[1]" to "87.2" which are the given values from this page.
https://docs.oracle.com/javase/tutorial/java/data/converting.html
Upon doing so I receive "requires two command-line arguments." which is the else part of the code. I'm pretty sure I am being oblivious to this. I have tried looking for anything regarding passing arguments but i can't find exactly what to do.
I have also tried creating two "string" values named one and two with the same values as above and inputting the string name into the args positions but still received the same outcome.
Is it something simple such as requesting an input from the user or should I manually put the values in there and if I need to add the values into the argument then how would I go about doing so.
The arguments passed to the main methods are the one typed when starting your java application from command line. An revelant example for your case would be :
java YourProgram 4.5 87.2
Then you will be able to access them from args[0] and args[1] as explained in the tutorial.
For more examples read the Command-Line arguments part of the java tutorial.
If you're running the program from a command line (typing something like java ValueOfDemo into a terminal), you would type java ValueOfDemo 4.5 87.2 to pass 4.5 and 87.2 as the first and second arguments, respectively. If you're running the program using an IDE such as Eclipse or NetBeans, search for that program's documentation on how to pass command line arguments to the program.
In general, command line arguments are arguments that are passed to the program you're running when the program is started. You can also ask the user for input while your program is running, but you would explicitly write code to do so and accept the value.
See this page for more information: https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html
Open cmd(window key + r) and compile by command: javac yourClass.java and then execute by command: java yourClass 4.5 87.2 you will see result
Just started to learn Scala :) The question right away: Why printing to stdout is so slow?
$ time scala -e 'val s = "foobarjoe!"; for (i <- 1 to 10000000) println(s)' > /dev/null
real 0m22.522s
user 0m14.252s
sys 0m8.508s
$ scala -version
Scala code runner version 2.11.4 -- Copyright 2002-2013, LAMP/EPFL
The same code in Perl as an example:
$ time perl -le '$s = "foobarjoe!"; for (1..10000000) { print($s) }' > /dev/null
real 0m1.276s
user 0m1.266s
sys 0m0.010s
This link answers the question: http://www.rgagnon.com/javadetails/java-0603.html
If your program is doing a lot printing to the console using System.out.println() then it is possible to get a good performance boost by using an alternative to do the console output.
By default, System.out.print() is only line-buffered and does a lot work related to Unicode handling. Because of its small buffer size, System.out.println() is not well suited to handle many repetitive outputs in a batch mode. Each line is flushed right away. If your output is mainly ASCII-based then by removing the Unicode-related activities, the overall execution time will be better.
It now remains to translate the solution from Java to Scala :)
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream(java.io.FileDescriptor.out), "ASCII"), 512);
Respected sir/madam,
I have a fortran exe which takes a input file and produces output file by doing some manipulation on input file.I am able to run the command in linux terminal.(I think fortran compiler is availble in linux).Now please suggest how to run this fortran executable file using java(in Linux machine).
What i attempted is,
String cmd="fortranExe arg1 arg2";
//fortranExe=exe path
//arg1,arg2 are arguments to fortran executable program
Process p=Runtime.getRuntime().exec(cmd);
But i am not getting output.When i tried to run Linux commands such as ls,dir are giving output.Is anything required for running fortran code in java?
Try using something like this
Process process = new ProcessBuilder("C:\\PathToExe\\fortran.exe","param1","param2").start();
Got this from
Java Programming: call an exe from Java and passing parameters
More info on ProcessBuilder: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ProcessBuilder.html
No, if it's a reqular binary for the platform you are running your JVM on, it shouldn't matter.
How are you running the binary, when you run from console?
Once the process was generated successfully, you can read its stdout like this:
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = br.readLine()) != null)
{
System.out.println(line);
}
br.close();
If there was any runtime problem executing the process, e.g. no permission to run the binary etc., the process.exitValue() will return 127.
EDIT:
seeing the other comments, I can see that you are using redirected in/output to your binary.
So in fact there are no parameters, but you need to open InputFileName.txt and use the process.getOutputStream() Object to write to your process. No need to set OutputFilename.txt, because you read the output from the InputStream and if necessary can write it yourself to a file.
This answer explains it in detail:
https://stackoverflow.com/a/3644288/435583
https://stackoverflow.com/a/6796053/435583
Cheers,
Apart from using Runtime, a more cleaner way will be to use JNA. See specific example for Fortran here.
You can even call individual pieces like subroutines of your Fortan program directly from Java. JNA is generally used to invoke C/C++ programs and are generally suited for this type of use cases and I guess yours use case fits well here.