1

I'm trying to do something similar to Question 4617364 but for Python - load a class from python script file, where said class implements a Java interface and hand it over to some Java code that can use its methods - but calls to the object method return invalid values and printing from the initializer doesn't seem to do anything.

My implementation looks like this:

Interface:

package some.package;
import java.util.List;
public interface ScriptDemoIf {
    int fibonacci(int d);
    List<String> filterLength(List<String> source, int maxlen);
}

Python Implementation:

from some.package import ScriptDemoIf

class ScriptDemo(ScriptDemoIf):
    """ Class ScriptDemo implementing ScriptDemoIf """

    def __init__(self):
        print "Script Demo init"

    def fibonacci(self, d):
        if d < 2:
            return d
        else:
            return self.fibonacci(d-1) + self.fibonacci(d-2)

    def filterLength(self, source, maxlen):
        return [ str for str in source if len(str) <= maxlen ]

Class loader:

public ScriptDemoIf load(String filename) throws ScriptException {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("jython");
    FileReader script = new FileReader(filename);
    try {
        engine.eval(new FileReader(script));
    } catch (FileNotFoundException e) {
        throw new ScriptException("Failed to load " + filename);
    }
    return (ScriptDemoIf) engine.eval("ScriptDemo()");
}

public void run() {
    ScriptDemoIf test = load("ScriptDemo.py");
    System.out.println(test.fibonacci(30));
}

(Obviously the loader is a bit more generic in real life - it doesn't assume that the implementation class name is "ScriptDemo" - this is just for simplicity).

When the code is being ran, I don't see the print from the Python's __init__ (though if I put a print in the body of the script then I do see that), but the test variable in run() look like a valid jython "proxy object" and I get no casting errors. When I try to run the fibonacci() method I always get 0 (even if I change the method to always return a fixed number) and the filterLength() method always returns null (probably something to do with defaults according to the Java interface).

what am I doing wrong?

Community
  • 1
  • 1
Guss
  • 30,470
  • 17
  • 104
  • 128
  • I've not used Jython, but `getEngineByName("jruby")` stands out. Surely that needs to be "jython"? – Thomas K Jan 06 '11 at 19:37
  • thanks for noticing that - I fixed. The code is basically the same, so I just copied from my previous question. sorry. – Guss Jan 06 '11 at 19:41
  • why there are `engine` and `m_engine`? – jfs Jan 19 '11 at 18:10
  • `getEngineByName("jython")` might be replaced by `.getEngineByName("python")`. – jfs Jan 19 '11 at 18:18
  • @J.F. Sebastian: m_engine is a copy&paste error. I've tried `getEngineByName("python")` initially and it didn't work. If it works with a current version I might change to that but more likely that I'll keep using "jython" as long as that works. – Guss Jan 20 '11 at 12:32

1 Answers1

2

What version of jython are you using? You might have run into the JSR223 Jython bug : http://bugs.jython.org/issue1681

From the bug description:

Calling methods from an embedded Jython script does nothing when using JSR-223 and Jython 2.5.2rc2, while Jython 2.2.1 just works fine.

Daniel Teply
  • 1,974
  • 1
  • 13
  • 10
  • Indeed, that is apparently the problem - I was using Jython 2.5.2rc2 and upgrading to Jython 2.5.2rc3 solved the problem for me. Thanks! – Guss Jan 20 '11 at 12:48