简体   繁体   English

从Java调用python函数的不同/更好的方法

[英]Different / better approaches for calling python function from Java

I am quite new to python and am trying to call python's function from java. 我是python的新手,我试图从java调用python的函数。

My primary requirements are these: 我的主要要求是:

  • call should be transparent, in the sense that it should not require modifying .py file simply to enable it to be called from java. call应该是透明的,因为它不应该只需要修改.py文件就可以从java调用它。 I might be given any python file with some functions inside it. 我可能会给它任何包含一些函数的python文件。 I should be able to call any of these functions without requiring to modify .py file. 我应该能够调用任何这些函数,而无需修改.py文件。
  • I want to be able to send arguments of both primitive types ( int , String , floats etc.) or non primitive types ( HashMap , ArrayList ) from java to python function and receive back the returned object (which may of primitive types or non-primitive types) from python to java. 我希望能够将原始类型( intStringfloats等)或非原始类型( HashMapArrayList )的参数从java发送到python函数并接收返回的对象(可能是原始类型或非原始类型)原始类型)从python到java。 I am also using pandas DataFrame and numpy ndarray and hence also want to be able to send and receive corresponding objects to and from java. 我也使用pandas DataFrame和numpy ndarray,因此也希望能够从java发送和接收相应的对象。
  • I preferably want to stick to CPython instead of Jython because I might need to use newer libraries that might not be available in Jython. 最好坚持使用CPython而不是Jython,因为我可能需要使用Jython中可能没有的新库。

There are several options that I found online. 我在网上找到了几个选项。 Few are: 很少有:

  • Use Jython's PythonInterpreter with which I am able to invoke python function without requiring any changes to .py script file: 使用Jython的PythonInterpreter ,我可以使用它来调用python函数,而无需对.py脚本文件进行任何更改:

    py1.py py1.py

      def square2(list): squares = [] for i in list: squares.append(i*i) return squares 

    JythonTest.groovy JythonTest.groovy

      import org.python.util.PythonInterpreter import org.python.core.*; class JythonTest { static main(def args) { PythonInterpreter pi = new PythonInterpreter() pi.exec("from py1 import square2") PyFunction pf = (PyFunction)pi.get("square2") println pf.__call__(new PyList([1,2,3,4]))[2] //9 } } 

    I am very well able to satisfy my needs. 我很能满足我的需求。 But its not CPython. 但它不是CPython。

  • Use ScriptEngine : This is very similar to PythonInterpreter. 使用ScriptEngine :这与PythonInterpreter非常相似。 But agains its Jython. 但它的Jython再次出现。 Also, unlike PythonInterpreter, we cannot work with Jython 2.5+ and cannot directly access PyObjects. 此外,与PythonInterpreter不同,我们无法使用Jython 2.5+并且无法直接访问PyObjects。 So this option can be very well closed. 所以这个选项可以很好地关闭。

  • Use py4j : Cant find example which is as minimal as in case of Jython PythonInterpreter 使用py4j :找不到Jython PythonInterpreter的最小例子
  • Use java2python . 使用java2python But not much information is given about calling python from java so that I can conclude whether my above requirements can be satisfied. 但是没有给出关于从java调用python的信息,因此我可以得出结论是否可以满足我的上述要求。 Can anyone shed more light on this? 任何人都可以对此有所了解吗? More specifically if we can write the code as minimal as the one in Jython PythonInterpreter. 更具体地说,如果我们可以将代码编写为Jython PythonInterpreter中的代码。
  • Use JPype : However after quick go through I feel I will not be able to write as minimal code as in case of Jython PythonInterpreter. 使用JPype :但是在快速浏览之后,我觉得我将无法像Jython PythonInterpreter那样编写最小代码。 Also I felt the project somewhat not under developement. 我觉得这个项目有点不发展。 Is it? 是吗?

It seems that Jython PythonInterpreter is the best choice if I have understood all above approaches correctly. 如果我正确理解了上述所有方法,似乎Jython PythonInterpreter是最佳选择。 Have I made mistakes while grasping them? 我在抓住它们时犯了错误吗? Also is there any other better option? 还有其他更好的选择吗?

@Mahesha999, regarding the ability to stick with CPython which seems important now from your last comment: @ Mahesha999,关于坚持使用CPython的能力,从你上次的评论中看起来很重要:

Jep is a good option to be able to run python code which uses calls to native, like pandas that you mentionned. Jep是一个很好的选择,能够运行使用本机调用的python代码,就像你提到的pandas一样。

You'll need to write some wrapping code because Jep only implements automatic conversion between Java and Python between the most used types, which pandas.DataFrame is not. 您需要编写一些包装代码,因为Jep只在最常用的类型之间实现Java和Python之间的自动转换,而pandas.DataFrame则不然。

However if your use case is not to complex, you can access your pandas objects as numpy.NDArray object by calling DataFrame.values on your dataframe instance, and Jep implement conversion to the Java class it embeds for NDArray. 但是,如果您的用例不复杂,则可以通过调用DataFrame.values实例上的numpy.NDArray将您的pandas对象作为numpy.NDArray对象访问,并将Jep实现转换为它为NDArray嵌入的Java类。

You can get back to Java values from python code you execute by using Jep.getValue(String pythonVariableName, Class clazz) 您可以使用Jep.getValue(String pythonVariableName, Class clazz)从您执行的python代码返回Java值

For example 例如

Jep jep = new Jep();
jep.eval("import my_script");
jep.eval("df = my_script.function_returning_a_dataframe()");
jep.eval("col = df.a_column.values");
NDArray myCol = jep.getValue("col", NDArray.class);

I do so on a project I coded in Python that I need to integrate as a plugin in a Java application, so far it works. 我在一个用Python编写的项目中这样做,我需要在Java应用程序中作为插件进行集成,到目前为止它的工作原理。

There is no current answer to this problem. 目前没有这个问题的答案。 Using CPython relies on the execution of Python bytecodes, which in turn requires that the Python interpreter be embedded in the execution environment. 使用CPython依赖于Python字节码的执行,而Python字节码又需要将Python解释器嵌入到执行环境中。 Since no Java runtime comes with an embedded Python interpreter, it really does look as though Jython is the best answer. 由于没有Java运行时附带嵌入式Python解释器,所以看起来好像Jython是最好的答案。

Sometimes the answer you want just isn't available! 有时你想要的答案是不可用的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM