Handling Python IO from Within Java - java

I am currently working on a Java project that will allow me to text edit, save, and then execute Python code. I have hit a snag with the execution of this code however.
For executing the code, I have been doing the following:
Process p = Runtime.getRuntime().exec("python someFileName.py",null,new File("someFilePath");
From here, I have a class that takes this process, and tries to take the input and output streams from the process. I have a Timer set with an action listener that will refresh every .01 second.
That is not the problem however. I can receive input just fine if my program consists solely of print statements in python.
If my program contains anything that requires it to block, either raw_input or time.sleep, nothing is displayed.
My actionPerformed method is as follows:
public void actionPerformed(ActionEvent e)
{
try
{
while(inStream.available() > 0)
{
System.out.print((char)inStream.read());
}
while(errStream.available() > 0)
{
System.out.print((char)errStream.read());
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
To handle output, I have a KeyListener on a JTextArea that will send the contents of that area to the output stream.
Whenever I have anything in my Python program that requires blocking, no matter what location in the program, the entire thing locks up.
For instance, I have this python program:
import time
print "Welcome to my Program!"
print "Performing calculations"
time.sleep(5)
num = 5
print "Adding 5 to your number"
for x in range(5):
num+=1
print num
print "Finished!"
Nothing will display for the time that it sleeps. I would assume that the things I receive in the Java program would be:
Welcome to my Program!
Performing calculations
...then nothing for five seconds...then
Adding 5 to your number
6
7
8
9
10
Finished!
But nothing is displayed at all until after 5 seconds has elapsed. So I can execute the program, wait 5 seconds, then a flood of text appears.
Or for using raw_input, the same thing happens. So in other words I cannot use this to prompt users for input.
I was hoping I could get some help with this blocking issue so that my text displays gradually as opposed to having to wait for everything to get out of the way with timers or input.
Any help or resources are appreciated. My current OS is a Mac, but I want any solution to be workable on Windows as well (if at all possible).

By default, python scripts run with buffered output. That means you may not see any stdout until the script exits and flushes. All you have to do is launch python with -u to request unbuffered output. Then you will see what you were expecting.
python -u someFileName.py

Related

Reading from keyboard and ignoring printed text

I am writing a java program (In Intellij) that accepts a command from the user and reacts to the command. The reaction is asynchronous (using a separate thread).
Scanner in = new Scanner(System.in);
String command = null;
do {
System.out.println("Enter command or q to exit: ");
command = in.nextLine();
System.out.println("Received "+command);
obj.react(command);
}while (!command.equals("q"));
The reacting object may take a while to react and prints a message after it finishes.
The problem is that if I start typing a command, and before I finish, the object prints something, the typed command is lost.
For example Here is a problematic scenario (The text in italics is the user input):
Enter command or q to exit:
go
Received go
goAgainobj finished reacting!
Received
In this case, when I Hit enter after the printed message, the received command is empty.
Is there any way to keep the typed characters even after something was printed?
If you use an actual console, printed output will not affect written input. If you type 'go' and the system prints 'Again', then the in-buffer still knows 'go'. This is unintuitive and bad to read, but it's practical to interrupt running scripts, or other programs.
This may already work on your IDE or your system, depending on OS ans IDE.
If you want something more 'pretty' then you need to fully control input and output, much like the 'top' command in linux (if you happen to know that).
You can handle this way of input better with the Console class. See: https://www.codejava.net/java-se/file-io/3-ways-for-reading-input-from-the-user-in-the-console #3
The most intuitive idea to solve your problem seems to read, and then remove all input at the time you want to print something, and reprint it, so you'd get:
> go
received go
obj finished reacting!
> go
...
You'd basically always print an input line yourself, after first reading and removing the already printed input. This is why you need the Console class, because there, input and output are synchronized, so if you print something, you know that no input will happen in the meantime.

(Blocking) interactive shell via ProcessBuilder

I built an interactive EXE which means that you can continuously send new commands to it and it will process them.
An automation of this can be implemented in Java according to this answer. However, when sending the command, the code will not wait till the command has finished. Instead, it will return the control back to the caller right away which might lead to race conditions: If the sent command was supposed to write a file, maybe the file isn't created yet before it is accessed. How can a command be sent, the output read and as soon as some input command is expected again, the sendCommand() call returns?
public synchronized void sendCommand(String command) throws IOException
{
byte[] commandBytes = (command + "\n").getBytes(UTF_8.name());
outputStream.write(commandBytes);
outputStream.flush();
}
Preferably also returning the process output in the meantime. This would be the default behavior of a non-interactive shell command which terminates once finished executing. read() blocks indefinitely until the process terminates and I do not want to hardcode the length of the expected process output or similar hacks to circumvent this shortcoming.
I decided to rewrite my binary to be non-interactive again. It turns out the expected performance gain was negligible so there was no more reason to keep it interactive and go through an increased implementation hassle.

Java Command Prompt Emulator

I'm trying to make a java program that commands through cmd.exe and prints their output. To do this, I'm using this code:
cmdLine = Runtime.getRuntime().exec("cmd.exe");
cmdLineOut = new BufferedReader(new InputStreamReader(cmdLine.getInputStream()));
cmdLineIn = new PrintWriter(cmdLine.getOutputStream());
// ...
cmdLineIn.println(command);
cmdLineIn.flush();
String s = null;
while ((s = cmdLineOut.readLine()) != null)
System.out.println(s);
Although, when input is given, the output is never printed.
EDIT: Solved
The cmdLineOut.readLine() doesn't return null when the input is empty, it freezes. Since readLine freezes at the end no other code is executed, I just put the printing of the readLine in a seperate thread.
If somebody wants to answer this better, go ahead.
You never actually execute the user's command, at least in the snippet you posted. Also, nearly all command prompt "commands" are actually just programs that are on the default program search path. You should probably just Runtime.getRuntime().exec(user_command) for each command. This means that you will have to set up the input and output streams like you have already done for each command. You are right to get input in a separate thread, since attempting to read input will block the current thread until there is actually input to read.
However, some commands, even under UNIX or Linux systems, are "built-in" (like cd), meaning that the command prompt (aka "shell") handles the commands internally. Your program will have to test the user input to see if they are calling a built-in, and specially handle calls to built-in commands. Your program should actually be portable to non-Windows computers. Of course, the user would use different commands (cp instead ofcopy), but the only part you would have to add would be handling for other OS' shells' lists of built-ins (or simply have your program implement a "cross-platform" set of built-ins - this is your shell program, you get to make the rules).

About Java ProcessBuilder's stream

first of all.. apologize what i can't upload code..
(thirdparty program is sdelete)
I'm work with third Party program on java ProcessBuilder.
like..
ProcessBuilder("cmd","/C","thirdParty.exe")
or
ProcessBuilder("thirdParty.exe");
and then.. I make two thread that using scanner that get ProcessBuilder's stream.
(one is input Stream print , other one is error Stream print)
When I execute this program.
It seems like fine at opening part. thirdParty program's opening Messages show up in console and .. according to priority.. Process percentage must show up, but doesn't..
Percentage not show up, but it's not hangs or frozzen..
thirdparty work's fine. Just Scanner can't get InputStream data.
(if not with java process, namely if i just execute program.. percentage show up properly)
and.. finally when thirdParty process finished.. all of percentage data show up at once!
is anyone know about this phenomenon?
advice please..

Program1.run(Program2); HowTo: Program2.finish()?Program1.continue():Program1.wait();

I have two Java programs. The "first"/"Main" one implements a search algorithm and the "other"/"second" one uses Repast simulation framework for running a Multi-agent simulation. In the "first" Java program I have the following code block:
Class Individual{
public int getvalue()
{
While (Condition is true)
{
Start_MAS(); //start the simulation by calling the "second" Repast simulation program
//which will write some values to a text file at the end of the simulation
//read text file and do some work with the values
}
}}
the MA simulation/"second" program will run the simulation until a specific condition is met or 900 time-steps has elapsed, and once the stop condition is met, the program will write some output to a text file, which is read by the "first" program.
Now my problem is that when I run the "first" program (which at some point calls/runs the second program/simulation), it does not wait for the simulation/"second" program to finish, but what happens is that after sometime of running the simulation/"second" program, the "first" program will continue running its own code which is reading the output text file so I get error that the text file is empty.
My question is how do I force the "first" program to wait or stop running its code until the "second"/ simulation program is finished (the stop condition has been met and output has been written to the text file)? I thought of using wait in the "first" program and notify in the "second" program as follows:
In the "first" program:
Class Individual{
public int getvalue()
{
While (Condition is true)
{
Start_MAS(); //start the simulation by calling the "second" program which will write some
//values to a text file at the end of the simulation
synchronized(this)
{
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//read text file and do some work with the values
}
}
In the "second" program:
public void step(){ //a function called in each time step in the simulation
If (Stop condition is met)
MyPackage.Individual.notify();
}
but if I do this, it will execute wait after returning from the "second" program, and also if I place it before the calling it will wait then start the simulation. Is using wait and notify the correct way to do this? Any suggestions or tips on how to accomplish this?
Thank you so much!
I suspect your Repast simulation is genuinely terminating early due to some difference in conditions between running it programatically from your first app and when you have tested the second program (Repast simulation) stand alone.
Therefore - I recommend that you put some debug statements in your stop condition block to check whether the simulation is genuinely stopping before returning. If so, you have a different question to ask about why the simulation is stopping, rather than one on processes/threads. e.g.
...
If (Stop condition is met)
{
System.out.println("Stop condition has been met at tick " +
RepastEssentials.getTickCount());
}
...
I also suggest you join the repast-interest list to get answers to these questions (I am not a member of the Repast project, but do use it regularly). These kinds of questions are often asked and resolved, the list is active.
N.B. most recent thread on this exact issue was resolved here (posted for reference - although looking at the numbers in there, maybe that question is from you?).

Categories

Resources