通过java调用bat,bat再启动tensorflow环境运行python项目代码
java->bat->python(tensorflow)
参考:https://blog.csdn.net/qq_26591517/article/details/80441540###
java代码
package luogu;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;
public class Luogu {
public static void main(String[] args) throws InterruptedException, IOException {
//下面通过cmd运行路径中的bat语句
Process process = Runtime.getRuntime().exec("cmd /c D:\\gxq\\sys\\foot\\online_rebuild_system\\online_rebuild_system\\data\\a.bat");
//由于我的python代码里有大量输出,会和java形成无限的阻塞,所以输出的东西要马上读取
new InputStreamRunnable(process.getErrorStream(), "Error").start();
new InputStreamRunnable(process.getInputStream(), "Info").start();
boolean code = process.waitFor(30,TimeUnit.MINUTES);
process.destroy();
}
}
class InputStreamRunnable extends Thread {
BufferedReader bReader = null;
String type = null;
public InputStreamRunnable(InputStream is, String _type) {
try {
bReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(is), "UTF-8"));
type = _type;
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
String line;
int lineNum = 0;
try {
while ((line = bReader.readLine()) != null) {
lineNum++;
System.out.println(type+":"+line);
}
bReader.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
bat脚本代码
c:
cd C:\Users\wyt.DESKTOP-SUI0MPS\Anaconda3\envs\tensorflow
python.exe D:\gxq\sys\foot\online_rebuild_system\online_rebuild_system\main_cmd.py
上面的脚本代码相当于模拟整个运行过程
c:表示切换到c盘
cd表示进入相应的tensorflow环境
python xxxx,表示用当前目录下的python来执行后面的路径中的py代码
注:这样的bat写法相当于后者python项目里面的都是绝对地址(因为我们的环境是在tensorflow环境文件夹中),所以后面的都得自己检查。
如果用相对路径,相当于要cd进入要执行的项目目录,然后调用tensorflow目录环境下的python来执行默认当前目录下的项目,这样的想法是好的,但是cmd会显示用路径地址打开的环境python找不到其它的库,也不知道如果解决。
所以最终采用了进入tensorflow环境的方法。
遇到的一些问题:
注:关于Runtime.getRuntime().exec的阻塞问题
在执行java调用时,发生了java代码的阻塞,python代码执行到某一步后无法执行,一关掉java之后python代码又正常执行,这就是阻塞的表现。原因是输出太多,缓冲区的东西来不及拿,阻塞了。
参考:http://bcxw.net/article/303.html
第一种方法 命令行指定输出(没试过)
spark-submit --class org.apache.spark.examples.SparkPi /opt/hadoop/spark-2.3.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.3.0.jar 10 1>/dev/null 2>&1 &
这样就不需要你读取输出流,直接输出到不存在的地方,2>&1表示错误信息和前面的正常信息也一样输出到/dev/null。&表示后台运行
第二种方法 用子进程读取输出流
读取输出流的多线程代码,可以公用重复使用,直接复制吧。
class InputStreamRunnable extends Thread {
BufferedReader bReader = null;
String type = null;
public InputStreamRunnable(InputStream is, String _type) {
try {
bReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(is), "UTF-8"));
type = _type;
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
String line;
int lineNum = 0;
try {
while ((line = bReader.readLine()) != null) {
lineNum++;
System.out.println(type+":"+line);
}
bReader.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
然后修改Runtime.getRuntime().exec代码
Process process = Runtime.getRuntime().exec(commond.toString());
new InputStreamRunnable(process.getErrorStream(), "Error").start();
new InputStreamRunnable(process.getInputStream(), "Info").start();
boolean code = process.waitFor(30,TimeUnit.MINUTES);
process.destroy();
再次测试发现所有的信息都打印出来了, Runtime.getRuntime().exec的阻塞问题也没有了。