-1

Using

String cmdString = "cmd.exe /c start python ";
Process p = Runtime.getRuntime().exec(cmdString);

I can open the command prompt and run python. I now want to interact with the command prompt. I have read that using

public static void main(String[] args)
{

    BufferedWriter writerToProc;

    String scriptPath = "C:\\Users\\MichaelMi\\Documents\\SourceTree\\NODE-Sensor-Configurator\\src\\application\\resources\\BACnet-CMD-Line-Upgrader\\UpgradeApplication.py";
    String iniPath = "C:\\Users\\MichaelMi\\Documents\\SourceTree\\NODE-Sensor-Configurator\\src\\application\\resources\\BACnet-CMD-Line-Upgrader\\BACpypes.ini";

    String execString  = "python " + scriptPath + " --ini " + iniPath;
    String cmdString = "cmd.exe /c start " + execString ;

    try {
        Process p = Runtime.getRuntime().exec(cmdString);


        writerToProc = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));

        writerToProc.write(cmdString);
        writerToProc.flush();

        writerToProc.write("whois\n");
        writerToProc.flush();

        readErrors(p);
        readOutput(p);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

public static void readOutput(Process p)
{
    BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
    Runnable task = new Runnable() {

        @Override
        public void run() {
            try {
                if(stdInput.ready())
                {
                    stdInput.lines().forEach((l) -> System.out.println(l));
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread backgroundThread = new Thread(task);
    backgroundThread.setDaemon(true);
    backgroundThread.start();
}

public static void readErrors(Process p)
{
    BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
    Runnable task = new Runnable() {

        @Override
        public void run() {
            try {
                if(stdError.ready())
                {
                    stdError.lines().forEach((l) -> System.out.println(l));
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    Thread backgroundThread = new Thread(task);
    backgroundThread.setDaemon(true);
    backgroundThread.start();
}

Is supposed to allow me to write to the open command prompt. However this is not working for me. I am getting no exceptions thrown or status errors. I simply do not know how to write to an open command prompt.

7
  • How do you know that you're getting no errors or exceptions? Are you reading from the Process's InputStream? The ErrorStream? And in separate threads? Please show us your minimal reproducible example code so we can see exactly what you're doing and more importantly, what you may be doing wrong. Also, don't use Runtime but rather the more recent ProcessBuilder. also the cmd String should be an array or ArrayList of Strings. Commented Jul 27, 2018 at 17:36
  • I edited the post to show the entire code. The stdInput and stdError are never ready. I never end up in the catch of the try catch. Nothing is ever posted to my opened command prompt Commented Jul 27, 2018 at 17:42
  • You may never know since all is being run in the same thread with blocking code. Please consider separating your input and output into different threads. Commented Jul 27, 2018 at 17:43
  • 1
    Don’t start a window, start python: Try String cmdString = "python"; Commented Jul 27, 2018 at 17:45
  • I have not ever seen .isReady used in any code examples for reading from a buffer. But could work. You would want to do what @HovercraftFullOfEels said; you could then write a parser that parses the stream and passes it to a handler or just write the code into the thread. BufferedReader br = new BufferedReader(fr); String s = null; while ((s=br.readLine())!=null) { System.out.println(s); } is the typical method for reading from a reader. Commented Jul 27, 2018 at 17:46

2 Answers 2

0

I see two problems in your code:

One problem is the used command-line:

cmd.exe /c start python This starts a new cmd.exe instance which itself the uses start to start a detached python process. The detached process is therefore not connected to your BufferedReader/BufferedWriter.

Your second problem is that python does not execute your "1+1" via stdin. You can simply verify that by creating a file test with the context 1+1\n and execute it on the console: python < test. You will see no output.

See also piping from stdin to a python code in a bash script.

Sign up to request clarification or add additional context in comments.

5 Comments

Well that makes perfect sense. So I already know that I can start a python script and send commands to it. I already have code working which does that. Is there a way to start my python script and see the output in a command prompt window?
Do you want to see the output or read it from within Java? The first is easy: just execute cmd.exe /c start python C:/pathxyz/yourpythonfile.py. Make sure your python file ends with time.sleep(5) otherwise the window is closed directly when your script finishes.
My issue is that the script waits for 3 commands. Whois, readhexfile, and sendfile. The send file takes 4 minutes. I am finding it difficult to update my java app UI since the send is blocking. My thought to fix this and put users at ease is to open a command prompt that will show them the progess
My be executing the python scripts from within your Java program via Jython is better?
So I have code that can execute the script. The whole issue is the UI sitting there for 4 minutes with no updates for the end user to see.
-1

In this case you need to close the input stream before you can read the output streams of the python process. If anyone knows a better way please let us know.

public static void main(String[] args) {
    String cmdString = "python";
    try {
        ProcessBuilder pb = new ProcessBuilder(cmdString);
        Process pr = pb.start();
        try (BufferedReader readerOfProc = new BufferedReader(
                new InputStreamReader(pr.getInputStream()));
                BufferedReader errorsOfProc = new BufferedReader(
                        new InputStreamReader(pr.getErrorStream()))) {

            try (BufferedWriter writerToProc = new BufferedWriter(
                    new OutputStreamWriter(pr.getOutputStream()));) {
                writerToProc.write("myVar=1+1\r\n");
                writerToProc.write("print(myVar)\r\n");
                writerToProc.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }

            String s;
            while ((s = readerOfProc.readLine()) != null) {
                System.out.println("stdout: " + s);
            }
            while ((s = errorsOfProc.readLine()) != null) {
                System.out.println("stdout: " + s);
            }

            System.out.println("exit code: " + pr.waitFor());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Hope this helps!

1 Comment

Why the downvote? The code works and answers OPs question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.