您当前的位置: 首页 >  Python

庄小焱

暂无认证

  • 3浏览

    0关注

    800博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java——java语言调用python脚本

庄小焱 发布时间:2021-08-11 18:53:43 ,浏览量:3

摘要

本文为大家介绍如何java调用python方法,在实际工程项目中可能会用到Java和python两种语言结合进行,这样就会涉及到一个问题,就是怎么用Java程序来调用已经写好的python脚本呢,一共有三种方法可以实现,具体方法分别为大家介绍:

1. Jython方式调用

Jython是一个Python语言在Java中的完全实现。Jython也有很多从CPython中继承的模块库。最有趣的事情是Jython不像CPython或其他任何高级语言,它提供了对其实现语言的一切存取。所以Jython不仅给你提供了Python的库,同时也提供了所有的Java类(反射使Jython能无缝地使用任何Java类)这使其有一个巨大的资源库。虽然上述网络上对Jython的描述看似很美好,但在实际使用的过程中会遇到很多的问题。最大的问题就是Jython在2015年停止更新,目前最新的是 Jython 2.7.0 Final Released(May 2015)。这就会导致Jython无法使用一些新的CPython库。当你只是想要使用Jython编写一些与Java程序混合的、简单的代码时是比较简单的——但是当你的程序需要导入很多外部库时,Jython总会出现问题。而且Jython的运行效率也不快。 首先加入Jython包,这里就有第一个坑,要注意添加的是jython-2.7-b1.jar而不是jython.jar。

import java.io.IOException;

import org.python.core.Py;
import org.python.core.PyFunction;
import org.python.core.PyObject;
import org.python.core.PySystemState;
import org.python.util.PythonInterpreter;

public class JythonMethod {
    public static void main(String[] args) throws IOException {
        PySystemState sys = Py.getSystemState();
        System.out.println(sys.path.toString());
        //由于Jython和JVM的ClassPath不一样,所以需要手动加入项目所需的库文件路径

        sys.path.add("xxx\\libs");//项目库文件

        sys.path.add("xxx\\Lib");//Python自带库文件

        System.out.println(sys.path.toString());


        // 1. Python面向函数式编程: 在Java中调用Python函数
        String pythonFunc = "./xxx/xxx.py";//Python文件路径


        //在JVM中创建一个“Python解释器”对象
        PythonInterpreter pi1 = new PythonInterpreter();
        // 加载python程序
        pi1.execfile(pythonFunc);
        // 调用Python程序中的函数
        PyFunction pyf = pi1.get("methodName", PyFunction.class);
        //写入方法所需的参数,注意要转换为Python的相应类型

        PyObject Res = pyf.__call__(Py.newString("xxx1"),Py.newString("xxx2"));

        System.out.println(Res);
        pi1.cleanup();
    }
}
2. 终端(命令行)调用

终端(命令行)调用就是老生常谈的东西了,直接使用Java代码执行一段终端(命令行)命令来调用Python文件,简单粗暴。

但这种方式也存在以下问题:

  • 对多线程的支持不好,在部署到服务器的情况下,每次运行都会开启一个终端,消耗资源。
  • 这种方法无法像调用一个方法一样随意传参,毕竟是命令行执行,参数选择无法像内置方法一样随意选择。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class RunnableDemo implements Runnable {
    String name = null;
    public RunnableDemo(String name) {
        this.name = name;
    }
    public void run() {
        //命令行参数(注意先把Python加入环境变量)

        String[] arguments = new String[] { "python", "C:/xxx/xxx.py", "arg1", "arg2"};

        try {
            Process process = Runtime.getRuntime().exec(arguments);
            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = null;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
            in.close();
            int re = process.waitFor();
            System.out.println(re);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class RuntimeMethod {
    public static void main(String[] args) throws IOException, InterruptedException {
          RunnableDemo r1 = new RunnableDemo( "Thread1");
          Thread t1 = new Thread(r1);
          t1.start();

          RunnableDemo r2 = new RunnableDemo( "Thread2");
          Thread t2 = new Thread(r2);
          t2.start();
          RunnableDemo r3 = new RunnableDemo( "Thread3");
          Thread t3 = new Thread(r3);
          t3.start();
    }
}
 3. Python的WebService

最后选择的是这种方法,虽然繁琐了一点,但是这种方法至少是上述三个方法中,部署到项目里最优雅的一种方式了。具体就是将Python算法写成一个WebService发布出去,在JavaWeb项目中使用HttpURLConnection进行调用。

优点:

  1. 多线程的事不用调用方头疼了,而是交给了WebService服务器

  2. 以soap格式传参,相对来说参数格式选择还算自由

缺点:

  1. 又需要多部署一个WebService服务器

  2. 以WebService方式调用,又多走了一步,性能可想而知不会很快。

1. Python使用spyne发布WebService 
from spyne import ServiceBase, Iterable, Unicode, Integer, Application, rpc
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
from wsgiref.simple_server import make_server


class HelloWorldService(ServiceBase):
    @rpc(Unicode, _returns=Unicode)
    def say_hello(self, name):
        strArg = 'Hello' + name
        return strArg

application = Application([HelloWorldService],
                          tns='spyne.examples.hello',             #设置NameSpace,需要在soap中用到

                          in_protocol=Soap11(validator='lxml'),
                          out_protocol=Soap11())
if __name__ == '__main__':

    wsgi_app = WsgiApplication(application)
    server = make_server('0.0.0.0', 8000, wsgi_app)
    server.serve_forever()
Java使用HttpURLConnection调用WebService
import java.io.*;

import java.net.HttpURLConnection;
import java.net.URL;

public class PyWSclient {

    public static void main(String[] args) throws Exception
    {
        String urlString = "http://localhost:8000/?wsdl";//wsdl文档的地址
        URL url = new URL(urlString);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();//打开连接

        String xmlFile = "./soapXML/soap.xml";//要发送的soap格式文件
        File fileToSend = new File(xmlFile);
        byte[] buf = new byte[(int) fileToSend.length()];// 用于存放文件数据的数组

        new FileInputStream(xmlFile).read(buf);

        //Content-Length长度会自动进行计算
        httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
        httpConn.setRequestMethod("POST");
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);

        OutputStream out = httpConn.getOutputStream();

        out.write(buf);
        out.close();

        if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK)
        {
            InputStreamReader is = new InputStreamReader(httpConn.getInputStream());
            BufferedReader in = new BufferedReader(is);
            String inputLine;
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream("result.xml")));// 将结果存放的位置
            while ((inputLine = in.readLine()) != null)
            {
                System.out.println(inputLine);
                System.out.print(inputLine);
                bw.write(inputLine);
                bw.newLine();
            }
            bw.close();
            in.close();
        }
        else{
            //如果服务器返回的HTTP状态不是HTTP_OK,则表示发生了错误,此时可以通过如下方法了解错误原因。
            InputStream is = httpConn.getErrorStream();    //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。
            InputStreamReader isr = new InputStreamReader(is,"utf-8");
            BufferedReader in = new BufferedReader(isr);
            String inputLine;
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream("result.xml")));// 将结果存放的位置
            while ((inputLine = in.readLine()) != null)
            {
                System.out.println(inputLine);
                bw.write(inputLine);
                bw.newLine();
                bw.close();
            }
            in.close();

        }
        httpConn.disconnect();
    }
}

来源:https://blog.csdn.net/qq_29797697/article/details/99414291?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.base

关注
打赏
1657692014
查看更多评论
立即登录/注册

微信扫码登录

0.3665s