在阅读和使用this article时,它假设我们有一个完整的对象定义,其中包含从python到java的类和映射(代理)对象。
是否可以仅从python中的一段代码中导入一个方法(未在类中定义,但使用内部python类),而不将其包装在类定义中(不使用上述工厂范例)。
我想从java做一些from myPyFile import myMethod
,然后直接从java使用myMethod(可能是一个静态方法?)?但是,如果这是可能的,我没有找到任何关于如何做的线索(文章中描述的接口内容可能仍然需要告诉Java如何使用myMethod?)
最好的问候。
编辑:我现在正在处理 Jython 2.5.2 ,因此它可能依赖于版本,将来会更容易吗?
编辑:以下回复丹尼尔:
下面是一个示例代码,用于重现我得到的错误,并从您的回复中获得一个有效的示例!
(好吧,从 yield -ed 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 + "]");
编辑:
回答关于“生成一个:”的部分java.lang.ClassCastException:org.python.core.PySingleton无法转换为MyInterface“ ......我的大多数误解和错误都归于此事实上,我忘记了从Python部分处理Java!(请参阅上面的代码,我将其保留为未经修正的事实,因为这不是我的主要问题,并且在实际形式中,它是关于这个主要问题的工作答案,非常感谢Daniel和Joonas,他帮助我理解。)因此,对于工厂范例,应该 NOT 忘记在其Python文件中添加足够的导入:
from testjython.interfaces import MyInterface #// defining method inside a MyInterface.java
class MyClass(MyInterface):
[...]
我遇到的另一个困难是正确处理导入和包。 顺便说一句,将此代码添加到上层代码将产生 TypeError:无法转换为org.python.core.PyList ,但这是另一个问题......
答案 0 :(得分:7)
您可以使用PyObject.__call__(Object... args)
来调用任何可调用的Python对象。您可以从java端获取表示函数的PyFunction,就像获取python employee类一样。
Alternativeley,您可以通过在从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
答案 1 :(得分:2)
不能仅导入方法,因为在Java中,方法(或函数)不是第一类对象,即没有首先引用某个类(或接口)就无法引用方法。甚至静态方法都包含在类中,您可以通过类对象引用它们。
但是,您可以非常接近Jython 2.5.2中引入的解决方案:Jython函数直接作为单个抽象方法Java接口的实现工作(请参阅http://www.zyasoft.com/pythoneering/2010/09/jython-2.5.2-beta-2-is-released/)。因此,您可以在Java中定义一个接口 - 它必须包含一个方法定义:
interface MyInterface {
int multiply(int x, int y);
}
在Jython中加上类似的东西:
myFunction = lambda x, y : x * y
并将其用作Java中的MyInterface
。您仍然必须使用某种工厂模式,如您链接的文章中所述,将Jython函数转换为Java,但是这样的工作(可能包含错误,但想法是):
PyObject myFunction = interpreter.get("myFunction");
MyInterface myInterface = (MyInterface)myFunction.__tojava__(MyInterface.class);
int x = myInterface.multiply(2, 3); // Should return 6.