运行 python 来自 java 的脚本并发送 input/output
Running python script from java and sending input/output
我正在编写一个 java 程序,需要 运行 一个 python 脚本。
该脚本将打印输出,java 需要阅读以了解脚本的进度。
为了能够在 运行ning 时暂停脚本,我希望它偶尔请求输入,只有当 java 给它输入时,脚本才会继续运行。
这是我的 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();
}
}
这是我的 python 脚本:
# coding=utf-8
import sys
print '1'
print '--INPUT--'
inum = sys.stdin.readline()
print '2'
print '--EOF--'
我试过 运行我的代码
sevenTry("python", "C:\Testing.py");
但在 java 一侧,它卡在 tReader 中的行:
String line = reader.readLine();
如果我从 python 文件
中取出输入行,程序就可以运行
inum = sys.stdin.readline()
使用
inum = raw_input()
仍然出现同样的问题(我使用 python 2.7)
这里最令人困惑的部分是我什至试图用 java 文件(而不是 python)
来测试它
sevenTry("java", "-classpath", "C:\class", "CheckCMD");
它甚至可以使用输入行
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--");
}
}
您可能已经注意到,这是一个与 Python 有关的问题。
如https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately、
所述
" 当进程 STDOUT 被重定向到终端以外的其他东西时,输出会被缓冲到某个 OS 特定大小的缓冲区(在许多情况下可能是 4k 或 8k)。 "
因此,您需要在每次调用 print
后调用 sys.stdout.flush()
。
或者,作为更好的选择,您可以使用 -u 参数更改进程的默认行为,以获得无缓冲的输出。
我正在编写一个 java 程序,需要 运行 一个 python 脚本。
该脚本将打印输出,java 需要阅读以了解脚本的进度。
为了能够在 运行ning 时暂停脚本,我希望它偶尔请求输入,只有当 java 给它输入时,脚本才会继续运行。
这是我的 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();
}
}
这是我的 python 脚本:
# coding=utf-8
import sys
print '1'
print '--INPUT--'
inum = sys.stdin.readline()
print '2'
print '--EOF--'
我试过 运行我的代码
sevenTry("python", "C:\Testing.py");
但在 java 一侧,它卡在 tReader 中的行:
String line = reader.readLine();
如果我从 python 文件
inum = sys.stdin.readline()
使用
inum = raw_input()
仍然出现同样的问题(我使用 python 2.7)
这里最令人困惑的部分是我什至试图用 java 文件(而不是 python)
sevenTry("java", "-classpath", "C:\class", "CheckCMD");
它甚至可以使用输入行
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--");
}
}
您可能已经注意到,这是一个与 Python 有关的问题。
如https://unix.stackexchange.com/questions/182537/write-python-stdout-to-file-immediately、
所述" 当进程 STDOUT 被重定向到终端以外的其他东西时,输出会被缓冲到某个 OS 特定大小的缓冲区(在许多情况下可能是 4k 或 8k)。 "
因此,您需要在每次调用 print
后调用 sys.stdout.flush()
。
或者,作为更好的选择,您可以使用 -u 参数更改进程的默认行为,以获得无缓冲的输出。