Jython中,从Java只使用一种方法在Python?(Jython, use only a me

2019-07-29 08:37发布

阅读和使用时, 这篇文章它假定我们有类和映射(代理)一个完整的对象定义从Python对象到Java。

是否有可能只导入从一块在Python代码的方法(在类中没有定义,但是使用内部蟒类),而不在类定义包裹它(不使用上述的工厂范例中)。

我会喜欢做某种from myPyFile import myMethod从Java,然后用myMethod的,直接从Java(也许作为一个静态方法?)? 但是,如果这是可能的,我没有找到如何做任何线索(在文章中所描述的接口的东西可能还是要告诉的Java如何使用myMethod的?)

最好的祝福。

编辑 :我现在正在处理的Jython 2.5.2,因此它可能在未来进行版本依赖和更容易?

编辑:在下面回复丹尼尔:

下面是一个示例代码,重现我得到的错误,并从你的有用的回复得到一个工作的例子!

(井在映射加一点其他的问题丢回给Java对象从产量 -ed的Python / Jython的结果)

(@Joonas,对不起,我已经修改我的代码,现在我不能够回踩,我曾经有过错误)

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)

#!/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-办法做到这一点,如果是的话,我真的很感兴趣:))

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 + "]");


编辑:

在回答自己的部分约“产生:‘java.lang.ClassCastException:org.python.core.PySingleton不能被转换为MyInterface的’......我的大部分误解和错误的地方,由于这样的事实,我已经忘了处理在Java和Python的一部分!(见上面我的代码,我把它裸关于这个事实,因为这不是我的主要问题,并在其实际的形式,它是关于这个主要问题工作的回答,非常感谢大牛和Joonas谁帮助我了解)所以对于工厂的模式,人们应该忘记适当的进口增加了Python的文件:

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

class MyClass(MyInterface):
    [...]

我有另外一个困难是要正确处理好进口和包。 顺便说一句,将此代码添加到上面的代码会产生一个类型错误:无法转换为org.python.core.PyList但这是另一个问题...

Answer 1:

您可以使用PyObject.__call__(Object... args)调用任何调用Python对象。 您可以从Java方面表示你的函数你例子越来越蟒蛇员工类的方法相同的PyFunction。

Alternativeley,可以通过调用隐藏该在Java端的单一方法接口后面__tojava__(Interface.class)上从Python解释检索的功能。 详细示例(实际测试!):Python文件:

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


Answer 2:

仅导入的方法是不可能的,因为在Java中,方法(或功能)不是第一类对象,即有没有办法提及的方法没有首先提到某一类(或接口)。 即使静态方法被包围在一类和你通过类对象引用它们。

但是,你可以得到相当接近,在Jython的2.5.2推出的解决方案:Jython的功能直接工作作为一个抽象方法的Java接口的实现(见http://www.zyasoft.com/pythoneering/2010/09/jython- 2.5.2-β-2-被发布/ )。 所以,你可以定义Java中的接口 - 这是至关重要的,它包含了一个方法的定义:

interface MyInterface {
    int multiply(int x, int y);
}

另外像这样在Jython中:

myFunction = lambda x, y : x * y

并使用它作为一个MyInterface Java编写的。 你仍然需要使用某种工厂模式,在文章中描述您联系,以获得Jython的功能到Java,但像这样的工作(可能包含错误,但这个想法是):

PyObject myFunction = interpreter.get("myFunction"); 
MyInterface myInterface = (MyInterface)myFunction.__tojava__(MyInterface.class);
int x = myInterface.multiply(2, 3); // Should return 6.


文章来源: Jython, use only a method from Python from Java?