为啥一个好好的岗位是Java开发工程师要去做写python呢?因为产品经理安排的(突然多少有点明白为啥程序员和产品经理会一直开撕)。由于在选择企业的时候没看清企业性质,看了要求以为就是互联网企业,现在看看初为社畜的我还是太天真了。不过既然这几天已经在写python脚本了,那也不能浪费这段时间的经历了,毕竟python的闪光点也不少。于是想一下如何与老本行Java联系起来,就有了这篇博文。
在使用Java调用python之前,需要导入依赖环境。如,在maven项目中,需要导入如下依赖
<dependency>
<groupId>org.pythongroupId>
<artifactId>jython-standaloneartifactId>
<version>2.7.0version>
dependency>
在Java类中调用python语句的方法如下
import org.python.util.PythonInterpreter
public class JavaRunPython {
public static void main(String[] args) {
//首先调用python的解释器
PythonInterpreter interpreter = new PythonInterpreter();
//选择执行的的Python语句
interpreter.exec("a='hello world'; ");
interpreter.exec("print a;");
}
}
这种方法用的不多、也不推荐大家使用。这里为了整个文章内容的完成性,我把这种方法放在这里。(控制台出现“ Failed to install ‘’: java.nio.charset.UnsupportedCharsetException: cp0”的红标时,不是出错了,而是兼容没做好,可以去运行配置中的Arguments中输入
-Dpython.console.encoding=UTF-8
)
在正常的情况下,Java工程师只需要调用python开发工程师写的脚本就行了,不会再在代码中加入python语句了。因为在Java语言中添加入其他语言,使Java的可读性下降、执行意义也不是很大(为了一两行代码,去导入python包的性价比太低;而且如果行数多了,就应该是集合成脚本并执行脚本了)
这种方式是有些Java程序员使用调用。首先将准备好的脚本,如plus.py
a = 1
b = 2
print a + b
则在Java中运行的模式是这样的:
import org.python.util.PythonInterpreter;
public class JavaPythonFile {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
//我在这里使用相对路径,注意区分
interpreter.execfile("./plus.py");
}
}
为什么推荐使用这种方式来调用python脚本呢?
答:由于这种办法可以让进程与程序交互。可以看到出现的问题,便于解决
如还是调用上面的脚本为例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class RuntimeFunction {
public static void main(String[] args) {
Process proc;
try {
/*
附加:
String[] args1=new String[]{"/home/huan/anaconda2/bin/python","/home/huan/myfile/pythonfile/helloword.py"};
Process pr=Runtime.getRuntime().exec(args1);
String数组里的那一行很重要
首先一定要设置好你所使用的python的位置,切记不要直接使用python,因为系统会默认使用自带的python,所以一定要设置好你所使用的python的位置,否则可能会出现意想不到的问题(比如说我使用的是anaconda中的python,而ubuntu系统会默认调用自带的python,而我自带的python中并没有numpy库,所以会造成相应的代码不会执行的问题,所以设置好python的位置是很重要的)。还有就是要设置好py文件的位置,使用绝对路径。在这里插入代码片
还有就是可以看出,此方法可以满足我们python代码中调用第三方库的情况,简单实用。
*/
proc = Runtime.getRuntime().exec("python ./plus.py");
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
proc.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
对以上代码的解释
首先,为什么要创建Process proc。我们可以去看官方文档:
The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process that can be used to control the process and obtain information about it. The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.
这段文字的意思是: ProcessBuilder.start()和Runtime.exec两个方法会生成一个本地的进程,然后返回一个Processs子类的实例。通过这个实例可以控制进程以及获得关于进程的信息。这个Process类为进程提供可用于执行来自的输入的方法,然后执行输出到这个进程中,等待完成后,检查进程退出时的状态,然后停止这个进程。——换句话说,这个实例就是监视整个进程的。
通过Process的getInputStream(),getOutputStream()和getErrorStream()方法可以得到输入输出流,然后通过InputStream可以得到程序对控制台的输出信息,通过OutputStream可以给程序输入指令,这样就达到了程序的交换功能。
改造一下python脚本,注意严格的缩进。
def add(a,b):
a = 1
b = 2
print a + b
return a+b
调用的代码
import org.python.core.PyFunction;
import org.python.core.PyInteger;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;
public class Function {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.execfile("./plus.py");
// 第一个参数为期望获得的函数(变量)的名字,第二个参数为期望返回的对象类型
PyFunction pyFunction = interpreter.get("add", PyFunction.class);
int a = 5, b = 10;
//调用函数,如果函数需要参数,在Java中必须先将参数转化为对应的“Python类型”
PyObject pyobj = pyFunction.__call__(new PyInteger(a), new PyInteger(b));
System.out.println("the anwser is: " + pyobj);
}
}
参考文献:
java调用python的几种用法(看这篇就够了)
在Java中调用Python
java调用python代码