问题描述:bug调试后发现阻塞在这一句Process .waitFor(),原因是错误信息得不到输出,缓冲池阻塞,得用错误输出流将他输出。
原因:
Runtime.getRuntime()返回当前应用程序的Runtime对象,该对象的exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。通过Process可以控制该子进程的执行或获取该子进程的信息。
它的所有标准io(即stdin,stdout,stderr)操作都将通过三个流(getOutputStream(),getInputStream(),getErrorStream())重定向到父进程。父进程使用这些流来提供到子进程的输入和获得从子进程的输出。因为输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流出现失败,当缓冲区满之后将无法继续写入数据,则可能导致子进程阻塞,最终造成阻塞在waifor()这里。
针对这种情况,解法是要清空getInputStream()和getErrorStream()这两个流。而且两个流的清空一定是异步的
解决方案:
//写一个一行行读取信息流的方法
public static String consumeInputStream(InputStream is) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String s ;
StringBuilder sb = new StringBuilder();
while((s=br.readLine())!=null){
System.out.println(s);
sb.append(s);
}
return sb.toString();
}
// 主程序
@RequestMapping("/forecast")
public ResponseData Opt3() throws JsonParseException, JsonMappingException, IOException {
//调用python
List<String> forecast_label1 = new ArrayList<String>();
try {
System.out.println("start");
String[] args3=new String[]{"D:\\Anaconda3\\python.exe", "E:\\桌面\\vue\\model_forecast.py"};
Process pr=Runtime.getRuntime().exec(args3);
//获取到Process 的所有错误信息,标准错误流(必须写在 waitFor 之前)
String errStr = consumeInputStream(pr.getErrorStream());
//获取到Process 的所有正常信息流信息并打印
String inStr = consumeInputStream(pr.getInputStream());
String errStra = consumeInputStream(pr.getErrorStream());
int retCode = pr.waitFor();//等待程序运行结束,返回值。
if(retCode == 0){
System.out.println("程序正常执行结束");
}
System.out.println("end");
forecast_label1.add("模型预测完成!");
} catch (Exception e) {
e.printStackTrace();
return null;
};
List<String> forecast_label = new ArrayList<String>();
forecast_label = forecast_label1;
forecast_label.remove("");
System.out.println(forecast_label);
Map<String, Object> result = new HashMap();
result.put("forecast_label", forecast_label);
return ResponseData.ok(result);
}
- 在python文件前面加上
import warnings
warnings.filterwarnings(‘ignore’) # “error”, “ignore”, “always”, “default”, “module” or “once”
这句话能够将所有警告不输出