Get data back from Jython scripts using JSR-223
Asked Answered
S

3

2

I am using Jython 2.5.1 with JSR-223 (i.e. javax.script package) and I expect the last line of the Python script to be returned. For example, after evaluating this script:

class Multiplier:

  def multiply(self, x, y):
    return x * y

Multiplier().multiply(5, 7)

I should get back 35, but I get null instead. In other hand it works with this other test:

5 * 7

What am I doing wrong?

Here's the Java code:

public static void main(String[] args) throws Exception {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");

    FileReader f = new FileReader("Multiplier.py");
    Object result = engine.eval(f);
    //assert(result == 35);
}

PS: It works fine with JRuby, Groovy and Rhino, i.e. the last line is always returned.

Thanks in advance.

Sharyl answered 11/12, 2009 at 10:59 Comment(0)
C
5

UPDATE: I was actually missing the goal (and problem) of the OP in my initial answer that has been clarified in a comment. I'm updating my answer accordingly.

First update the Multiplier.py script as below:

class Multiplier:

  def multiply(self, x, y):
    return x * y

x = Multiplier().multiply(5, 7)

Then call it like this from the Java code:

public static void main(String[] args) throws Exception {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");

    FileReader f = new FileReader("Multiplier.py");
    engine.eval(f);
    Object x = engine.get("x");
    System.out.println("x: " + x);
}

I get the following output when running the code above:

x: 35
Centiare answered 11/12, 2009 at 12:44 Comment(4)
The Java code is pretty much what you've written and I manage to print the result as you've done. What I really need is to get the result after calling engine.eval(f) instead of just printing it, e.g. Object result = engine.eval(f);Sharyl
Assigning the result to a variable and getting it from the engine after evaluation works perfectly, thanks! However I still wonder why the behavior I have with other engines doesn't apply to Jython. I'll leave the question opened for a while, maybe someone knows.Sharyl
Good question. Let's see if someone has an answer (I don't).Centiare
According to the tests I made with Rhino, you should be able to write something like: Object return_value = engine.eval(f); System.out.println("return_value = " + Object.toString()); Maybe that's a new feature, I see this post is quite old already.Plimsoll
C
5

This is a Python language issue more than a Jython or JSR 223 issue. Python differentiates between expressions (which have values) and statements (which don't). The script you're passing is a statement. If you passed an expression, it'd have a value.

The reason you're seeing something different with Ruby and JavaScript is that compound statements have the value of the last statement evaluated. For example, compare Ruby:

>> (2 ; 3) + 5
=> 8
>> (x = 5) + 7
=> 12

with Python:

>>> (2 ; 3) + 5
  File "<stdin>", line 1
    (2 ; 3) + 5
       ^
SyntaxError: invalid syntax
>>> (x = 5) + 7
  File "<stdin>", line 1
    (x = 5) + 7
       ^
SyntaxError: invalid syntax

JavaScript seems to be somewhere in between. Like Ruby, assignments evaluate to the value assigned. However, the last evaluated statement in a block is returned but not usable as part of an expression:

> { 2 ; 3 }
3
> { 2 ; 3 } + 5
5
> (x = 5) + 7
12
Carpenter answered 15/12, 2009 at 23:38 Comment(0)
E
2

I had the same problem. I have written a scripting library that supports JSR223 and have submited http://bugs.jython.org/issue1798:

$ python
Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x=5<br/>
>>> x<br/>
5
>>>

At least if you eval("x=5\nx") it seems like you would get the value back.

Enthusiasm answered 4/10, 2011 at 22:34 Comment(1)
Even in C python, eval("x=5\nx") fails... so it's just a bad language feature I guess.Fernanda

© 2022 - 2024 — McMap. All rights reserved.