简体   繁体   English

从Java运行python脚本并发送输入/输出

[英]Running python script from java and sending input/output

I am writing a java program that will need to run a python script. 我正在编写一个需要运行python脚本的Java程序。
The script will print output which will java need to read to know the progress of the script. 该脚本将打印输出,java需要读取该输出以了解脚本的进度。
To be able to pause the script while running I want it to ask for input once in a while, only when java give it input the script will keep going. 为了能够在运行时暂停脚本,我希望它不时地要求输入一次,只有当Java给它输入时,脚本才能继续运行。
Here is my Java method: 这是我的Java方法:

private static void sevenTry(String[] strCommands) throws IOException {
    Object oLock1 = new Object();
    Object oLock2 = new Object();

    ProcessBuilder pBuilder = new ProcessBuilder(strCommands);
    pBuilder.redirectErrorStream(true);
    Process proc = pBuilder.start();

    Thread tReader = new Thread() {
        @Override
        public void run() {
            System.out.println("~~tReader starting~~");
            BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            synchronized (oLock1) {
                try {
                    String line = reader.readLine();
                    while (line != null && !line.trim().equals("--EOF--")) {
                        System.out.println("Stdout: " + line);
                        if (line.trim().equals("--INPUT--")) {
                            synchronized (oLock2) {
                                oLock2.notify();
                            }
                            oLock1.wait();
                        }
                        line = reader.readLine();
                    }
                } catch (IOException e) {
                    System.out.println("tReader: " + e.getMessage());
                } catch (InterruptedException e) {
                    System.out.println("tReader: " + e.getMessage());
                } catch (Exception e) {
                    System.out.println("tReader: " + e.getMessage());
                }
            }
            System.out.println("~~tReader end~~");
            synchronized (oLock2) {
                oLock2.notify();
            }
        }
    };
    Thread tWriter = new Thread() {
        @Override
        public void run() {
            System.out.println("~~tWriter starting~~");
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));

            String line, input;
            Scanner scan = new Scanner(System.in);

            synchronized (oLock2) {
                try {
                    oLock2.wait();
                } catch (InterruptedException e1) {
                    System.out.println("tWriter: " + e1.getMessage());
                }
            }
            while (tReader.isAlive()) {
                synchronized (oLock1) {
                    System.out.println("Java: insert input");
                    scan.hasNext();
                    input = scan.nextLine();
                    try {
                        writer.write(input + "\n");
                        writer.flush();
                    } catch (IOException e) {
                        System.out.println("tWriter: " + e.getMessage());
                    }
                    oLock1.notify();
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                    System.out.println("tWriter: " + e1.getMessage());
                }
            }
            System.out.println("~~tWriter end~~");
        }
    };

    tReader.start();
    tWriter.start();
    System.out.println("~~everything submitted~~");
    try {
        tReader.join();
        tWriter.join();
        System.out.println("~~finish~~");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

This is my python script: 这是我的python脚本:

# coding=utf-8
import sys

print '1'
print '--INPUT--'
inum = sys.stdin.readline()
print '2'
print '--EOF--'

I tried running my code 我尝试运行我的代码

sevenTry("python", "C:\\Testing.py");

but on java side it get stuck inside tReader at line: 但在Java方面,它卡在tReader中,位于以下行:

String line = reader.readLine();

The program does work if i take out the input line from the python file 如果我从python文件中取出输入行,该程序就可以工作

inum = sys.stdin.readline()

Using 使用

inum = raw_input()

still bring up the same problem (im using python 2.7) 仍然提出同样的问题(使用python 2.7)
The most confusing part here that i even tried to test this with a java file (instead of python) 这里最令人困惑的部分是,我什至尝试使用Java文件(而不是python)对其进行测试

sevenTry("java", "-classpath", "C:\\class", "CheckCMD");

and it worked even with the input lines 它甚至可以与输入线一起使用

import java.util.Scanner;

public class CheckCMD {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String line;
        System.out.println("1");
        System.out.println("--INPUT--");
        in.hasNext();
        line = in.nextLine();
        System.out.println("2");
        System.out.println("--EOF--");
    }
}

As you may have noticed, this is a problem related to Python. 您可能已经注意到,这是与Python有关的问题。

As described in https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately , https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately中所述

" when process STDOUT is redirected to something other than a terminal, then the output is buffered into some OS-specific-sized buffer (perhaps 4k or 8k in many cases)." “当进程STDOUT重定向到终端以外的其他地址时,输出将被缓冲到特定于操作系统大小的缓冲区中(在许多情况下可能为4k或8k)。”

So, you need to call sys.stdout.flush() after each invoke to print . 因此,您需要在每次调用print之后调用sys.stdout.flush()

Or, as a better option, you can change the default behaviour for the process, using the -u param, to get unbuffered output. 或者,作为更好的选择,您可以使用-u参数更改进程的默认行为,以获取无缓冲的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM