java调用python文件之第三方包路径
没有用java调用过python的同学,可以先查看如下文章:
http://www.cnblogs.com/u0mo5/p/4032452.html
http://blog.csdn.net/ztf312/article/details/51338060#
http://blog.csdn.net/thorny_v/article/details/61417386
先说一下我的环境:eclipse,jdk1.7,python2.7.8,第三方包:python for arcgis
根据网上资料得知,java调用python脚本约有3种方式:直接执行python脚本、执行脚本文件、Runtime.getRuntime()执行。其中前两个都用的PythonInterpreter。
方式一:
直接执行python就不多说了,代码如下:
import javax.script.*;
import org.python.util.PythonInterpreter;
import java.io.*;
import static java.lang.System.*;
public class FirstJava
{
public static void main(String args[])
{
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("days=('mod','Tue','Wed','Thu','Fri','Sat','Sun'); ");
interpreter.exec("print days[1];");
}
}
方式二:
执行py文件如下:
首先创建py脚本test.py,定义一个add方法
def add(a,b)
return a+b
新建java程序执行py脚本
import org.python.core.PyFunction;
import org.python.core.PyInteger;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;
public class FirstJava
{
public static void main(String args[])
{
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.execfile("C:\\Python27\\programs\\test.py"); //要执行py脚本的文件路径
PyFunction func = (PyFunction)interpreter.get("add",PyFunction.class); //py脚本中要执行的方法名称
int a = 32, b = 23 ;
PyObject pyobj = func.__call__(new PyInteger(a), new PyInteger(b)); //给add方法传参数
System.out.println("anwser = " + pyobj.toString());
}
}
输出结果为55。
这里有个弊端,即本文要解决的问题:简单的py脚本还可,如果引用的第三方包,会报错:java
ImportError: No module named xxx
ps:这里所说的报错前提是,能成功独立运行引用第三方包的py脚本。如果直接执行py脚本,都报第三方包找不到,那是你python环境就没设好,不是java调用python的问题。
ps的ps:网上搜ImportError错误,也有一些解决方案,不过按照那些说法,没解决。
下面说第三种方法,也是本文想提供的一种方式。
方式三:
先说一下网上的示例:
Runtime rt = Runtime.getRuntime();
System.out.println("start");
Process proc = Runtime.getRuntime().exec("python outfile.py");
proc.waitFor();
System.out.println("end");
可以看到这是一种类似于调用控制台执行python脚本的方式,由此给了我一些启发:
利用控制台启动python,执行python脚本,是不是等同于直接运行py脚本呢?
可不可以把一个脚本当做一个方法,利用控制台将参数传递进去?
答案是可以的。示例如下:
java:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
public class FirstJava
{
public static void main(String args[])
{
Integer a = 1, b = 2;
String[] argg = new String[] { "python", currentPath+"/src/main/java/test.py", a, b};
Process pr = Runtime.getRuntime().exec(argg);
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line;
String result = "";
while ((line = in.readLine()) != null) {
// line = decodeUnicode(line);
result += line;
}
in.close();
pr.waitFor();
}
}
注:argg参数既可以是String型,形如”python xx/xxx/test.py a b”;也可以是String[]型,形如{“python”,”xx/xxx/test.py”,a,b}。
第一个参数默认python(猜测是程序名称)
第二个参数是py脚本的绝对路径
后面的参数是要传给py脚本的值
对应py脚本:
import sys
import arcpy #第三方包
a = sys.argv[1] #接收第一个参数
b = sys.argv[2] #接收第二个参数
print a+b
这样,python就能接收到java传递的参数,还不会报第三方包异常了。
缺点也是有的:把一个python文件当做一个方法来使用,就没有return了,用print 返回给java,在java中in.readLine()接收。如果py脚本中执行了N次print,java中in.readLine()也会接收N次。
第一次接触python,查了不少资料才勉强解决。如果你有疑问或更好的方法,欢迎留言。
转载自:https://blog.csdn.net/rrrrroy_Ha/article/details/75105732