一、起因

开始是没像用这么麻烦的方式去搞一些计算的,直接用java去算就得了,但是架不住python搞一些公式计算确实方便,而且公式过于复杂再java写一遍,着实闲的腚疼所以还是直接在java中调用python会省力一点,但调试会有点麻烦,相比与重写一遍公式这点麻烦也就不麻烦了

二、思路

网上查看了一些资料,有两种处理方案,一个弄个python编译器去处理,一种是调用控制台的形式去执行,对于本人需求来说还是控制台比较直白,没啥弯弯绕所以没啥好犹豫的就选了这个路线

三、具体实施

虽然没有用到是用python编译器的方式但是作为笔记记录还是需要记录一下滴

1、python编译器法

过程–>new PythonInterpreter --> 获取python文件路径 --> 指定执行那个函数–>传入指定的格式的参数–

import org.python.util.PythonInterpreter;
public class CallPythonFun {
    public void testForInterpreter() {
        PythonInterpreter interpreter = new PythonInterpreter();
        try {
            String fileUtl = this.getClass().getResource("scrapdataForJava.py").getFile();
            interpreter.execfile(fileUtl);
            // 第一个参数为期望获得的函数(变量)的名字,第二个参数为期望返回的对象类型
            PyFunction pyFunction = interpreter.get("downloadStock", PyFunction.class);
            //调用函数,如果函数需要参数,在Java中必须先将参数转化为对应的“Python类型”
            //PyString task = new PyString("volumnEnerge3");
            //PyInteger delay = new PyInteger(20);
            //PyInteger loop = new PyInteger(10);
            PyInteger threadNum = new PyInteger(8);
            PyString startDate = new PyString("");
            PyInteger model = new PyInteger(1);
            PyObject pyobj = pyFunction.__call__(threadNum, startDate, model);
            //PyObject pyobj = pyFunction.__call__(task, delay, loop);
            System.out.println("the anwser is: " + pyobj);
        } catch (NullPointerException e) {
            System.out.println("文件为空");
        }

    }
}

2、控制台法

过程:开一个控制台proc–> 获取文件路径–>准备参数–>执行–获取执行时打印的日志
关键:这种方式默认执行的文件种的main方法,没有要加上否则没啥效果,传进去的参数都是文本的要自己内部转化成想要的数据类型。

public void testForConsole() throws IOException {
        Process proc;
        try {
            String analyzemethods = this.getClass().getResource("analyzemethods.py").getFile().substring(1);
            System.out.println(analyzemethods);
            String[] args = {"python", analyzemethods, "20","10"};
            proc = Runtime.getRuntime().exec(args);// 执行py文件

            //用输入输出流来截取结果
            BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()
                    , Charset.forName("GBK")));
            String line = null;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
            in.close();
            proc.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

python文件中要做的相应改动,文件最开始的一行写上 #-- coding:UTF-8 – 否则也是执行不了

# 对变量做相应的类型转换
def volumnEnergyCaller(delay,loop):
    delay = int(delay)
    loop = int(loop)
    taskDispatch(volumnEnerge3, delay, loop)
#  sys.argv[1] 指的是第一个参数
if __name__ == '__main__':
    volumnEnergyCaller(sys.argv[1],sys.argv[2])

四、后续

java代码的编写以及python文件的改造都是小问题,本人由于系统是部署在linux环境中,linux自带的python是2.7的版本,所以事情变得又复杂了,其中印象比较深刻的点在在于python包的搜索路径的配置还是比较有意思的,因为本人的python代码引用了一个自定义类,在ide中使用的时候还没感觉,拉到控制台去执行一直报包找不到,也是挠了好一会的头。解决的办法做了如下一点小小的心得记录

1.做一个测试用的test.py
#-- coding:UTF-8 --
import sys
if __name__ == "__main__":
	print(sys.path)
2.分别在idel中的控制台与cmd的控制台去执行这个文件

我用的ideal去试的

java 调用linux shell Java 调用python脚本 坑_python


执行完会发现两个结果是不一样的,把不一样的路径手动添加到python文件中,这样包就不会报找不到的问题了

# 添加路径的语句
最好加在 import sys 的下一行,当然 import sys 自己要处在一堆import之前的
sys.path.append('D:\\study\\lib\\site-packages')

结尾:至于python3在linux上的配置就不细聊了,也是麻烦。有需要的话留言开个新文章介绍好了。