【发布时间】:2018-09-07 06:33:26
【问题描述】:
在为子流程运行创建管理器时遇到一些问题。在这样的子进程中是 python 脚本。我需要在不同的线程中写入/读取/包装进程的错误。我创建了一些简单的测试:
test.py
import sys
if __name__ == "__main__":
print ("START TEST SCRIPT")
print ("SOME STRING")
for line in sys.stdin:
print ("DEBUG>>> "+ line)
并创建一个简单的java测试类:
public class Test {
public static void main(String[] args) {
ProcessBuilder builder = new ProcessBuilder("python", "test.py");
builder.environment().put("PYTHONIOENCODING", "UTF-8");
builder.directory(new File("./test/external_processes/python"));
try {
Process environmentProcess = builder.start();
InputStream out = environmentProcess.getInputStream();
InputStream err = environmentProcess.getErrorStream();
OutputStream in = environmentProcess.getOutputStream();
Thread t1 = new Thread(() -> {
OutputStreamWriter writer = new OutputStreamWriter(in);
try {
writer.write("new string");
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
byte[] buffer = new byte[4096];
int count;
try {
while ((count = out.read(buffer)) >= 0) {
System.out.println("[TASK STREAMER] " + new String(buffer, 0, count));
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(() -> {
byte[] rbuffer = new byte[4096];
int rcount;
try {
int rno = err.available();
while ((rcount = err.read(rbuffer)) >= 0) {
System.out.println("[TASK STREAMER ERR] " + rno + " :: " + new String(rbuffer, 0, rcount));
}
err.close();
} catch (IOException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
environmentProcess.waitFor();
System.out.println("ok!");
environmentProcess.getInputStream().close();
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
一切顺利
Connected to the target VM, address: '127.0.0.1:50726', transport: 'socket'
[TASK STREAMER] START TEST SCRIPT
SOME STRING
DEBUG>>> new string
Disconnected from the target VM, address: '127.0.0.1:50726', transport: 'socket'
ok!
Process finished with exit code 0
直到我决定不写任何东西输出,所以我删除了线程 t1。之后,无法从 python 到达前两行(“START TEST SCRIPT”,“START TEST SCRIPT”)并且执行被卡住。
如果代码如下所示:
import java.io.*;
public class Test {
public static void main(String[] args) {
ProcessBuilder builder = new ProcessBuilder("python", "test.py");
builder.environment().put("PYTHONIOENCODING", "UTF-8");
builder.directory(new File("./test/external_processes/python"));
try {
Process environmentProcess = builder.start();
InputStream out = environmentProcess.getInputStream();
InputStream err = environmentProcess.getErrorStream();
Thread t2 = new Thread(() -> {
byte[] buffer = new byte[4096];
int count;
try {
while ((count = out.read(buffer)) >= 0) {
System.out.println("[TASK STREAMER] " + new String(buffer, 0, count));
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
});
Thread t3 = new Thread(() -> {
byte[] rbuffer = new byte[4096];
int rcount;
try {
int rno = err.available();
while ((rcount = err.read(rbuffer)) >= 0) {
System.out.println("[TASK STREAMER ERR] " + rno + " :: " + new String(rbuffer, 0, rcount));
}
err.close();
} catch (IOException e) {
e.printStackTrace();
}
});
t2.start();
t3.start();
t2.join();
t3.join();
environmentProcess.waitFor();
System.out.println("ok!");
environmentProcess.getInputStream().close();
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我会做到的:
Connected to the target VM, address: '127.0.0.1:50726', transport: 'socket'
我知道该进程不会因为 python 等待输入而停止,但我至少期望两个前字符串(“START TEST SCRIPT”、“START TEST SCRIPT”)。
但是如果我先关闭输出流,我会到达这个字符串。任何人都可以帮助我理解这种情况,以及如果子进程内部有以太输入读写输出,如何达到子进程输出?
附言对不起我的俄语语法。
【问题讨论】:
-
显示发生错误行为之后的代码。
-
已添加代码
-
你的python版本是什么?
-
python 3.5.some
-
让人们以他们想要的方式编写他们的第三方脚本很重要。
标签: java python multithreading io subprocess