Jython,只使用Java中的Python方法? [英] Jython, use only a method from Python from Java?

查看:278
本文介绍了Jython,只使用Java中的Python方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读并使用这篇文章时假设我们有一个完整的对象定义,包含从python到java的类和映射(代理)对象。

When reading and using this article it assumes that we have a full object definition with class and mapping (proxy) objects from python to java.

是否可以只导入一个方法(未在类中定义) ,但是使用内部python类)来自python中的一段代码而不将其包装在类定义中(不使用上面描述的工厂范例)。

Is it possible to only import a method (not defined inside a class, but using internal python class) from a piece of code in python without wrapping it in a class definition (without using the factory paradigm described above).

我会喜欢从myPyFile导入某种从java导入myMethod ,然后直接从java使用myMethod(可能作为静态方法?)?但是,如果这是可能的,我没有找到任何关于如何做的线索(文章中描述的接口内容可能仍然需要告诉Java如何使用myMethod?)

I would have like to do some kind of from myPyFile import myMethod from java, and then use myMethod, directly from java (maybe as a static method ?) ? But if this is possible, I do not have found any clue of how doing that (the interface stuff described in the article may be still necessary to tell Java how to use myMethod ?)

祝你好运。

编辑:我现在正在处理 Jython 2.5.2 ,所以它可能依赖于版本,将来会更容易?

EDIT : I am now dealing with Jython 2.5.2, so it may be version dependent and much more easier in future ?

编辑:以下回复丹尼尔:

下面是一个示例代码,重现我得到的错误,并从您有用的回复中获得一个有效的示例!

Here is a sample code, to reproduce the error I get, and also get a working example from your helpful reply!

(好吧,并添加一些其他问题从 yield -ed Python / Jython结果映射回Java对象)

(Well and add a little other question on the mapping back to Java objects from a yield -ed Python/Jython result)

(@ Joonas,抱歉,我修改了我的代码,现在我无法退回到以前的错误。

(@Joonas, Sorry, I have modified my code, and now I am not able to step back to the error that I used to have)

import org.python.core.Py;
import org.python.core.PyList;
import org.python.core.PyTuple;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PySystemState;
import org.python.util.PythonInterpreter;

interface MyInterface {
    public PyList getSomething(String content, String glue, boolean bool);
}
class MyFactory {

    @SuppressWarnings("static-access")
    public MyFactory() {
        String cmd = "from mymodule import MyClass";
        PythonInterpreter interpreter = new PythonInterpreter(null, new PySystemState());

        PySystemState sys = Py.getSystemState();
        sys.path.append(new PyString("C:/jython2.5.2/Lib"));

        interpreter.exec(cmd);
        jyObjClass = interpreter.get("MyClass");
    }

    public MyInterface createMe() {
        PyObject myObj = jyObjClass.__call__();
        return (MyInterface)myObj.__tojava__(MyInterface.class);
    }

    private PyObject jyObjClass;
}


public class Main {

    public static void main(String[] args) {

    /*
// with only :
    PythonInterpreter interpreter = new PythonInterpreter();

     i get : 
Exception in thread "main" Traceback (most recent call last):
  File "<string>", line 1, in <module>
LookupError: no codec search functions registered: can't find encoding 'iso8859_1'

which is probably due to the : 
#!/usr/bin/env python
# -*- coding: latin-1 -*-

// yes i am from France, so my - sorry for that - bad english ;) and have to deal with non 127 ascii chars :)
     */

    PythonInterpreter interpreter = new PythonInterpreter(null, new PySystemState());

    PySystemState sys = Py.getSystemState();
    sys.path.append(new PyString("C:/jython2.5.2/Lib"));

    interpreter.exec("from mymodule import getSomething"); 
    PyObject tmpFunction = interpreter.get("getSomething"); 
    System.err.println(tmpFunction.getClass()); 
    MyInterface i = (MyInterface) tmpFunction.__tojava__(MyInterface.class); 
    System.err.println(i.getSomething("test", " - ", true));
    for (Object x : i.getSomething("test", " - ", true)) {
        System.out.println(x);
        // How can i get back an equivallent of the Python _"for (a, b) in getSomething:"_ 
        // with _"a"_ being PyUnicode or better String, and _"b"_ being boolean ?
    }

    // ^^ so adapting Daniel Teply solution works ! Thanks to him... 
    // BTW the part below did not work : but i may have missed or/and also mixed many things :/
    // i feel Jython damned hard to dive in :/ 
    // and really hope that the sample that i post and answers that i get will help others to swim!

    try {
        MyFactory factory = new MyFactory();
        MyInterface myobj = factory.createMe();

        PyList myResult = myobj.getSomething("test", " - ", true);
        System.out.println(myResult);
    }
    catch (Exception e) {
        System.out.println(e);
        // produce a : java.lang.ClassCastException: org.python.core.PySingleton cannot be cast to MyInterface
        // EDIT : see below last edit, this error may be due to my forgotten heritage from interface in the python code!
    }

    System.exit(-1);
    }
}

Python部分:(mymodule.py)

Python part: (mymodule.py)

#!/usr/bin/env python
# -*- coding: latin-1 -*-

class MyClass:
    def __init__(selfself):
        pass
    def getSomething(self, content, glue = '', bool = True):
        for x in range(5):
            yield (glue.join(map(str, (content, x, chr(97 + x))))), bool
        #return list()

def getSomething(content, glue = '', bool = True):
    print "test"
    myclass = MyClass()
    return list(myclass.getSomething(content, glue, bool))

def main():
    test()

if __name__ == "__main__":
    main()

编辑

部分回答我自己,对于内心问题(内部评论):

(实际上我觉得我的答案和代码很难看,但是它起作用并且似乎没有 - 元组我不知道是否有更好的Jythonic方式,如果是这样,我真的很感兴趣:))

Partially answering myself, for the inner question (inside comments):
(actually I feel my answer and code are ugly, but it works and seems to be ok to un-tuple I do not know if there is a better Jythonic-way to do it, if so, I am really interested :))

for (Object x : i.getSomething("test", " - ", true)) {
    System.out.println(x);
    // How can i get back an equivallent of the Python _"for (a, b) in getSomething:"_ 
    // with _"a"_ being PyUnicode or better String, and _"b"_ being boolean ?

    // answering myself here :
    PyTuple mytuple = (PyTuple) x; // casting back x as PyTuple, can we have a java equivalent to _`(a, b) = x_ ? not sure...
    PyObject a = mytuple.__getitem__(0);
    PyObject b = mytuple.__getitem__(1);
    String aS = a.toString(); // mapping a unicode python string to java is as simple?
    boolean bB = b.toString().toLowerCase().equals("true");
    System.out.println(mytuple + "[" + aS + "][" + b + "][" + bB + "]");



编辑:



回答关于生成a:的部分java.lang.ClassCastException:org.python.core.PySingleton无法转换为MyInterface ...大多数由于我忘记了从Python部分处理Java这一事实,我的误解和错误!(参见上面的代码,我对此事进行了不修正,因为这不是我的主要问题,并且以其实际形式,关于这个主要问题,这是一个有效的答案,非常感谢Daniel和Joonas帮助我理解。)因此对于工厂范例,应该 NOT 忘记在其Python文件中添加足够的导入:




Answering myself to the part about "produce a : "java.lang.ClassCastException: org.python.core.PySingleton cannot be cast to MyInterface"... most of my misunderstanding and errors where due to the fact that I had forgotten to handle the Java from the Python part! (see my code above, I leave it uncorrected about this fact because it was not my main question, and in its actual form, it's a working answer about this main question, many thanks to Daniel and Joonas who helped me to understand). So for the factory paradigm, one should NOT forget to add the adequate import to its Python file :

from testjython.interfaces import MyInterface #// defining method inside a MyInterface.java

class MyClass(MyInterface):
    [...]

我遇到的另一个困难是正确处理导入和包。
BTW,将此代码添加到上层代码将产生 TypeError:无法转换为org.python.core.PyList ,但这是另一个问题......

One other difficulty that I had was to correctly handle the import and packages. BTW, adding this code to the upper code will produce a TypeError: can't convert to org.python.core.PyList but this is another concern...

推荐答案

您可以使用 PyObject .__ call __(Object ... args)来调用任何可调用的Python对象。您可以从java端获取代表您的函数的PyFunction,就像您获取python员工类一样。

You can use PyObject.__call__(Object... args) to invoke any callable Python object. You can get the PyFunction representing your function from the java side the same way you example is getting the python employee class.

Alternativeley,您可以将它隐藏在单个方法接口之后在Java端通过调用从Python解释器检索的函数的 __ tojava __(Interface.class)
详细示例(实际测试!):
python文件:

Alternativeley, you can hide this behind a single method interface on the java side by calling __tojava__(Interface.class) on the function you retrieved from the Python interpreter. Detailed example (actually tested!): python file:

def tmp():
    return "some text"

java:

public interface I{
    public String tmp();
}

public static void main(String[] args) {
    PythonInterpreter interpreter = new PythonInterpreter();
    interpreter.exec("from test import tmp");
    PyObject tmpFunction = interpreter.get("tmp");
    System.err.println(tmpFunction.getClass());
    I i = (I) x.__tojava__(I.class);
    System.err.println(i.tmp());

}

输出:

class org.python.core.PyFunction
some text

这篇关于Jython,只使用Java中的Python方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆