当前位置: 首页 > 知识库问答 >
问题:

Jython,只使用来自Python和Java的方法?

公良鸿禧
2023-03-14

这里是一个示例代码,重现我得到的错误,也得到一个工作示例从您的有益的答复!

(好的,添加一个关于从生成的Python/Jython结果映射回Java对象的其他问题)

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


编辑:

回答我自己关于“Produce a:”java.lang.ClassCastException:org.python.core.PySingleton不能强制转换到MyInterface“的部分...我的大部分误解和错误都是由于我忘记了从Python部分处理Java!(请参阅上面的代码,我没有更正它,因为它不是我的主要问题,而且在它的实际形式中,它是关于这个主要问题的有效答案,这要感谢Daniel和Joonas帮助我理解)。因此,对于工厂范例,不要忘记向其Python文件添加适当的导入:

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

class MyClass(MyInterface):
    [...]

我遇到的另一个困难是正确处理进口和包装。顺便说一句,将此代码添加到上层代码将产生一个TypeError:不能转换为org.python.core.pylist但这是另一个问题...

共有1个答案

督德明
2023-03-14

您可以使用pyobject.__call__(object...args)调用任何可调用的Python对象。您可以从java端获得表示您的函数的PyFunction,就像您的示例获得python employee类一样。

或者,您可以通过调用从Python解释器中检索的函数__tojava__(interface.class)将其隐藏在java端的单个方法接口之后。详细示例(实际测试!):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
 类似资料:
  • 我试图使用java通过jython.jar运行python函数。我使用的是一个从web下载的python模块,它需要python 2.6或更高版本。我很确定我的python版本是2.7.2。但是,当我尝试运行java程序时,它继续报告检测到python 2.5。我如何解决这个问题? 我的代码是: 而错误是:

  • 问题内容: 我刚刚开始在我的Java类中使用from,它很棒!但是,如果尝试包含python模块(,等),则会收到以下异常(用于): 如何从jython jar中使类“查看” python可用的模块? 问题答案: 您嵌入了jython,将使用一些Python模块: 如果要在Java代码中设置路径(sys.path): Py在org.python.core中。 rootPath和modulesDir

  • 我编写了一个由五个。py脚本文件组成的Python程序。我希望从Java应用程序中执行这些python脚本的主要部分。 我有什么选择?使用PythonInterperter不起作用,例如,模块不能从Jython中加载(我不希望用户为这些依赖项的工作而确定他的Python路径)。 我使用Jython的CompileAll将整个文件夹编译为。class文件。我能以某种方式嵌入这些。class文件以从J

  • 我想使用jython执行一个Python函数,这个函数位于我的一个Java Python项目中。https://smart bear . com/blog/test-and-monitor/embedding-jython-in-Java-applications/给出了示例代码。但是在我的场景中,我得到了下面的异常。 线程“main”回溯中出现异常(最近一次调用是最后一次):文件“”中第1行,导

  • 我想从java代码调用python并将参数传递给python中的函数。我已经在python中封装了一个函数。但问题是我还在python程序中导入了第三方库skLearning。当我调用测试程序并将值传递给python时,我能够运行代码。但是当我尝试在python代码中使用第三方库,例如skLearning和import时,我得到了以下错误。 我初始化了Python解释器类的对象,然后使用以下命令,

  • 我的Jython脚本调用了一些我用Java编写的代码(因为我更喜欢Java多线程)。现在,我需要从Java调用一个Jython方法(否则我必须用Java重写它)。 从Jython中驱动Java很容易,设置Java是主程序,Jython是从程序也很简单,但如何设置它以使它们能够相互调用并不明显。 官方文档包含了一篇关于这一切的非常长的文章:第10章:Jython和Java集成,这使得这项任务乍一看似