Error while trying to setup a Jython interpreter
Question: I wanted to boot up a Jython interpreter inside the plugin, then execute files
inside the interpreter.

    
    
    package com.jakob.jython;
    
    import org.bukkit.plugin.java.JavaPlugin;
    import org.python.core.PyObject;
    import org.python.util.PythonInterpreter;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.logging.Logger;
    
    public class EmbeddedJython extends JavaPlugin {
    
        private static final Logger log = Logger.getLogger("Minecraft");
        private PythonInterpreter interpreter;
        private PyObject plugin;
    
    
        public void onEnable() {
            log.info("JythonTest enabled");
            this.interpreter = new PythonInterpreter();
            log.info("Jython interpreter fired up and cooking on gas");
    
            log.info("Loading Python Plugin");
    
            InputStream pythonScript = EmbeddedJython.class.getResourceAsStream("MyPlugin.py");
            this.interpreter.execfile(pythonScript, "MyPlugin.py");
    
            log.info("Getting plg method.");
            this.plugin = this.interpreter.get("plg");
            log.info("Plugin loaded");
            log.info(plugin.invoke("onEnable").toString());
        }
    
        public void onDisable() {
            log.info(plugin.invoke("onDisable").toString());
            log.info("Jython disabled");
        }
    
    }
    

In other tests I can get the Jython interpreter up and running strings I hand
it but when I use the above snippet I end up with an exception that looks
something like this:

    
    
    11:03:38 [SEVERE] Error occurred while enabling JythonTest v0.12 (Is it up to da
    te?): null
    java.io.IOException: Stream closed
            at java.io.BufferedInputStream.getInIfOpen(Unknown Source)
            at java.io.BufferedInputStream.fill(Unknown Source)
            at java.io.BufferedInputStream.read(Unknown Source)
            at org.python.core.ParserFacade.adjustForBOM(ParserFacade.java:371)
            at org.python.core.ParserFacade.prepBufReader(ParserFacade.java:298)
            at org.python.core.ParserFacade.prepBufReader(ParserFacade.java:288)
            at org.python.core.ParserFacade.parse(ParserFacade.java:183)
            at org.python.core.Py.compile_flags(Py.java:1717)
            at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java:235
    )
            at com.jakob.jython.EmbeddedJython.onEnable(EmbeddedJython.java:26)
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:125)
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader
    .java:750)
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManage
    r.java:253)
            at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:132)
            at org.bukkit.craftbukkit.CraftServer.loadPlugins(CraftServer.java:110)
            at net.minecraft.server.MinecraftServer.e(MinecraftServer.java:218)
            at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:205)
            at net.minecraft.server.MinecraftServer.init(MinecraftServer.java:145)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:265)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:394)
    
    java.io.IOException: java.io.IOException: Stream closed
    
            at org.python.core.PyException.fillInStackTrace(PyException.java:70)
            at java.lang.Throwable.<init>(Throwable.java:181)
            at java.lang.Exception.<init>(Unknown Source)
            at java.lang.RuntimeException.<init>(Unknown Source)
            at org.python.core.PyException.<init>(PyException.java:46)
            at org.python.core.PyException.<init>(PyException.java:43)
            at org.python.core.Py.JavaError(Py.java:481)
            at org.python.core.ParserFacade.fixParseError(ParserFacade.java:104)
            at org.python.core.ParserFacade.parse(ParserFacade.java:186)
            at org.python.core.Py.compile_flags(Py.java:1717)
            at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java:235
    )
            at com.jakob.jython.EmbeddedJython.onEnable(EmbeddedJython.java:26)
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:125)
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader
    .java:750)
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManage
    r.java:253)
            at org.bukkit.craftbukkit.CraftServer.loadPlugin(CraftServer.java:132)
            at org.bukkit.craftbukkit.CraftServer.loadPlugins(CraftServer.java:110)
            at net.minecraft.server.MinecraftServer.e(MinecraftServer.java:218)
            at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:205)
            at net.minecraft.server.MinecraftServer.init(MinecraftServer.java:145)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:265)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:394)
    Caused by: java.io.IOException: Stream closed
            at java.io.BufferedInputStream.getInIfOpen(Unknown Source)
            at java.io.BufferedInputStream.fill(Unknown Source)
            at java.io.BufferedInputStream.read(Unknown Source)
            at org.python.core.ParserFacade.adjustForBOM(ParserFacade.java:371)
            at org.python.core.ParserFacade.prepBufReader(ParserFacade.java:298)
            at org.python.core.ParserFacade.prepBufReader(ParserFacade.java:288)
            at org.python.core.ParserFacade.parse(ParserFacade.java:183)
            ... 13 more
    

Could it be I'm using `execfile` wrong? Or is it an error or something I'm
missing in how `InputStream` works?


Answer: Are you sure that `EmbeddedJython.class.getResourceAsStream("MyPlugin.py");`
is finding the resource?

If it can't find the resource, `getResourceAsStream` will return a `null`, and
it is possible that the Jython interpreter will treat that as an empty
(closed) stream.

Your application should probably check this, rather than assuming that
`getResourceAsStream` has succeeded.

* * *

> If I `private File pythonFile = new File('MyScirpt.py');` and then hand
> `getResourceAsStream(pythonFile.getAbsolutePath());`

That won't work. The `getResourceAsStream` method looks for resources on the
classloader's classpath, and expects a path that can be resolved relative to
some entry on the classpath.

You probably want to do this:

    
    
    private File pythonFile = new File('MyScirpt.py');
    InputStream is = new FileInputStream(pythonFile);
    

and pass the `is` to the interpreter. You also need to arrange that the stream
is **always** closed when the interpreter has finished ... by whatever
mechanism that happens.

