Java调用python脚本,BufferedReader的readline函数无任何输出结果,进程长时间卡住

Java调用python脚本,BufferedReader的readline函数无任何输出结果,进程长时间卡住

最近在做项目时,需要用到Java调用python文件并读取运行结果。一般Java调用简单的Python文件(不包含第三方库的)是没有任何问题的,但是我需要用到tensorflow、keras、numpy等第三方库,所以遇到了很多麻烦,经过各种百度查找,最终解决了问题,在这里做一个总结归纳。

问题1 Java调用python返回值一直为null

这个问题是我没有创建虚拟环境造成的,因为自己电脑上用的一直是Anaconda安装时自带的python,没有创建自己的虚拟环境,因此在Java中调用python文件时,就会找不到各种第三方库的问题。

问题2 BufferedReader的readline函数无任何输出结果,进程长时间卡住

这个问题我也找了很多方法才解决,产生这个问题的主要原因是:
命令在运行的过程中会向标准输出或者标准错误输出写出数据,但JVM又没有去读,导致缓冲区满,进而导致进程阻塞。因为我的python文件调用的tensorflow,他会输出一堆警告信息,这些警告信息属于错误流(ErrorStream),如果我们没有及时处理,就会导致缓冲区占满,从而导致进程阻塞。

Process.getInputStream()和Process.getErrorStream()分别返回Process的标准输出流和错误流,两个流如果处理不当,其缓冲区不能被及时清除而被塞满,则进程被阻塞,即使调用Process.destory()也未必能销毁被阻塞的子进程。

这个问题的解决的方法比较简单,既然问题是缓冲区满之后没有及时清理,那么只要在Java代码里去读一下数据,保证缓冲区不会满即可.
具体代码如下:

public static void main(String[] args) {
        try{
            System.out.println("start");
            //一定要用虚拟环境下的python路径
            String[] args1=new String[]{"D:\\SoftWare\\Anaconda\\envs\\jst\\python.exe","F:\\Python_Project\\test.py"};
            Process pr = Runtime.getRuntime().exec(args1);

            // 防止缓冲区满, 导致卡住
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    String line;
                    try {
                        BufferedReader stderr = new BufferedReader(new InputStreamReader(pr.getErrorStream(),"GBK"));
                        while ((line = stderr.readLine()) != null) {
                            System.out.println("stderr:" + line);
                        }
                    }
                    catch (Exception e) {

                    }

                }
            }.start();

            System.out.println("==============打印结果==============");
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    String line;
                    try {
                        BufferedReader stdout = new BufferedReader(new InputStreamReader(pr.getInputStream(),"GBK"));
                        while ((line = stdout.readLine()) != null) {
                            System.out.println("stdout:" + line);
                        }
                    }
                    catch (Exception e) {

                    }
                }
            }.start();

            int exitVal = pr.waitFor();
            if (0 != exitVal) {
                System.out.println("执行脚本失败");
            }
            System.out.println("执行脚本成功");



        } catch (Exception e){
            e.printStackTrace();
        }
    }
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值