2

I created a default Maven Java project and added the following dependency:

<dependency>
  <groupId>org.python</groupId>
  <artifactId>jython</artifactId>
  <version>2.7.0</version>
</dependency>

Then I created a package src/main/java/mypkg and added this class:

package mypkg;

import javax.script.*;

class JythonMinimalTest {
    public static void main(String[] args) throws Exception {
        String engineName = "python";
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName(engineName);
        if (engine == null) {
            System.err.println("ERROR: `" + engineName + "` not available.");
            System.err.println("Available engines: ");
            for (ScriptEngineFactory factory: manager.getEngineFactories()) {
                System.err.println(factory);
                System.err.println("names:");
                for (String name: factory.getNames()) {
                    System.err.println("  " + name);
                }
            }
            System.exit(999);
        }
        engine.eval("print('hello, world')");
    }
}

When I run it using exec:java,

mvn exec:java -Dexec.mainClass=mypkg.JythonMinimalTest

I get the following mysterious output:

ERROR: `python` not available.
Available engines: 
org.python.jsr223.PyScriptEngineFactory@2b0e6c89
names:
  python
  jython
jdk.nashorn.api.scripting.NashornScriptEngineFactory@46618cb8
names:
  nashorn
  Nashorn
  js
  JS
  JavaScript
  javascript
  ECMAScript
  ecmascript

The manager returns null, but then in the next line lists python/jython among the available script engines.

Nashorn worked just fine in exactly the same way. What am I doing wrong with Jython?

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • What version of Java are you using? – Elliott Frisch Oct 15 '18 at 22:22
  • 1
    https://stackoverflow.com/a/33025866/2834978 – LMC Oct 15 '18 at 22:23
  • @ElliottFrisch maven uses both 1.8: `1.8 1.8`, the java itself is also `1.8.0`. – Andrey Tyukin Oct 15 '18 at 22:26
  • What happens if you use `jython-standalone` as artifactId instead of `jython` (see comment by Luis Muñoz)? – mzjn Oct 16 '18 at 15:18
  • @mzjn Indeed, with jython-standalone 2.7.1, I don't need any `Option.loadSite=false` hacks, it works as expected right away. Note that `jython-standalone.jar` takes 40MB instead of 30MB. This solution is mentioned in {the question linked by Andrew in {the question linked by Luis Muñoz}}: [whats-the-difference-between-jython-standalone-2-7-0-jar-and-jython-2-7-0-jar](https://stackoverflow.com/questions/30061490/whats-the-difference-between-jython-standalone-2-7-0-jar-and-jython-2-7-0-jar), but it has no accepted answers... – Andrey Tyukin Oct 16 '18 at 17:17
  • There are other similar questions, for example https://stackoverflow.com/q/17749799/407651 and https://stackoverflow.com/q/14641917/407651. The `Lib` subdirectory with standard Python modules (including site.py) is included in jython-standalone.jar but not in jython.jar. – mzjn Oct 16 '18 at 17:24

3 Answers3

9

Here is one workaround:

Add this at the top:

import org.python.core.Options;

Before invoking getEngineByName, set

   Options.importSite = false;

Then the engine is created without problems.

Got the solution from this conversation.


Another solution that works well (proposed by mzjn in the comments) is to replace the jython artifact by jython-standalone.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
1

You either need to disable importSite with python Options, as you already discovered. Or, set the python.home to where you have extracted jython. I have it extracted in my home folder under jython2.7.0; adding this,

System.setProperty("python.home", new File(
        System.getProperty("user.home"), "jython2.7.0").getPath()
);

allows python to discover the correct PYPATH so it can build the python environment.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • Forgive me this possibly dumb question, but what do you mean by "extract"? I didn't extract anything anywhere, I just added five lines to the POM and hoped that I can use the engine just like any other dependency. I'm afraid that I still don't understand what the `importSite` option does, and what `site.py` is good for. Will I get into trouble as soon as I try to go beyond `print('hello')` if `site.py` isn't imported? What difference does it make? – Andrey Tyukin Oct 15 '18 at 22:40
  • Install jython using the [installer file](http://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7.0/jython-installer-2.7.0.jar) from their website, it contains a `Lib` folder. That contains a bunch of `python` modules that it uses to form the base python system. So you can `import io` or `import pickle` etc. – Elliott Frisch Oct 15 '18 at 23:05
0

One way to fix this is to set the env var jythonpath to include the specific Lib directory you need for your instance (and include the Lib\site-packages as well to avoid further issues with specific packages)

roetzi
  • 974
  • 7
  • 10