Jython: Packing several .py on .jar, problem importing .py moduleswithin the .jar

Discussion in 'Python' started by Gubatron, Dec 3, 2008.

  1. Gubatron

    Gubatron Guest

    Hello all,

    I've a problem with Jython and importing .py inside a jar.

    I'm putting .class and .py files inside .jar files.

    myjar.jar
    MyJar\SomeClass.class
    MyJar\main.py
    MyJar\otherModule.py

    So I add the myjar.jar to Jython's sys.path

    org.python.core.PySystemState pySys = new
    org.python.core.PySystemState();
    pySys.path.insert(0,new PyString("/path/to/myjar.jar"));

    and execute main.py

    //We pass the PythonInterpreter the modified PySystemState
    PythonInterpreter i = new PythonInterpreter(null, pySys);

    //Find the entry in the jar for the python file and execute it.
    //It should be able to find any resource inside the jar.
    JarFile jFile = new JarFile("/path/to/myjar.jar");
    ZipEntry zipEntry = jFile.getEntry("MyJar/main.py");

    InputStream pythonInputStream =
    jFile.getInputStream(zipEntry);
    i.execfile(pythonInputStream);

    main.py will execute fine, it'll be able to do

    from MyJar import SomeClass

    with no problem

    However, If I try to import the other .py in the same jar, it won't
    find it:

    from otherModule import *

    or

    from MyJar.otherModule import *

    I always get this:

    ImportError: no module named otherModule

    at org.python.core.Py.ImportError(Unknown Source)
    at org.python.core.imp.import_first(Unknown Source)
    at org.python.core.imp.import_name(Unknown Source)
    at org.python.core.imp.importName(Unknown Source)
    at org.python.core.ImportFunction.load(Unknown Source)
    at org.python.core.ImportFunction.__call__(Unknown Source)
    at org.python.core.PyObject.__call__(Unknown Source)
    at org.python.core.__builtin__.__import__(Unknown Source)
    at org.python.core.imp.importFromAs(Unknown Source)
    at org.python.core.imp.importFrom(Unknown Source)
    at org.python.pycode._pyx1.f$0(<iostream>:26)
    at org.python.pycode._pyx1.call_function(<iostream>)
    at org.python.core.PyTableCode.call(Unknown Source)
    at org.python.core.PyCode.call(Unknown Source)
    at org.python.core.Py.runCode(Unknown Source)
    at org.python.util.PythonInterpreter.execfile(Unknown Source)

    I've tried adding more paths to sys.path, with no luck:

    pySys.path.insert(0,new PyString("/path/to/myjar.jar/MyJar"));
    pySys.path.insert(0,new PyString("file:jar:/path/to/myjar.jar!"));

    and nothing works, any ideas would help. I know this has to work,
    because I previously had a problem where I couldn't do

    import os

    and then I added the "Lib/" folder inside jython.jar and now I'm able
    to import all those standard jython modules, so, somehow, jython is
    able to import .py within a .jar, help would be very much appreciated.

    Angel Leon
     
    Gubatron, Dec 3, 2008
    #1
    1. Advertising

  2. Gubatron

    Gubatron Guest

    Re: Jython: Packing several .py on .jar, problem importing .pymodules within the .jar

    I've managed to solve this problem.

    I can now run a python script that lives inside a Jar. The python
    script is now able to import other scripts within the same jar, and
    it's also able to import java classes that live within the jar.

    The problem was solved by giving the Jython Interpreter the proper
    initialization. This entails:

    - Giving it a class loader that has put the Jar on it's class path
    - Adding the path of the jar to the interpreter's sys.path

    Here's an example:


    org.python.core.PySystemState pySys = new
    org.python.core.PySystemState();
    pySys.setClassLoader(((URLClassLoader) classLoaders.get(jarFile)));

    //We also have to pass the jar to JYTHON_PATH (sys.path)
    //so that it can properly import inner python modules.
    pySys.path.insert(0,new PyString(jarFile));

    //We pass the PythonInterpreter the modified PySystemState
    PythonInterpreter i = new PythonInterpreter(null, pySys);
    i.exec(pythonScriptName);





    On Dec 3, 6:31 am, Gubatron <> wrote:
    > Hello all,
    >
    > I've a problem with Jython and importing .py inside a jar.
    >
    > I'm putting .class and .py files inside .jar files.
    >
    > myjar.jar
    >   MyJar\SomeClass.class
    >   MyJar\main.py
    >   MyJar\otherModule.py
    >
    > So I add the myjar.jar to Jython's sys.path
    >
    >                         org.python.core.PySystemState pySys = new
    > org.python.core.PySystemState();
    >                         pySys.path.insert(0,new PyString("/path/to/myjar.jar"));
    >
    > and execute main.py
    >
    >                         //We pass the PythonInterpreter the modified PySystemState
    >                         PythonInterpreter i = new PythonInterpreter(null, pySys);
    >
    >                         //Find the entry in the jar for the python file and execute it.
    >                         //It should be able to find any resource inside the jar.
    >                         JarFile jFile = new JarFile("/path/to/myjar.jar");
    >                         ZipEntry zipEntry = jFile.getEntry("MyJar/main.py");
    >
    >                         InputStream pythonInputStream =
    > jFile.getInputStream(zipEntry);
    >                         i.execfile(pythonInputStream);
    >
    > main.py will execute fine, it'll be able to do
    >
    > from MyJar import SomeClass
    >
    > with no problem
    >
    > However, If I try to import the other .py in the same jar, it won't
    > find it:
    >
    > from otherModule import *
    >
    > or
    >
    > from MyJar.otherModule import *
    >
    > I always get this:
    >
    > ImportError: no module named otherModule
    >
    >         at org.python.core.Py.ImportError(Unknown Source)
    >         at org.python.core.imp.import_first(Unknown Source)
    >         at org.python.core.imp.import_name(Unknown Source)
    >         at org.python.core.imp.importName(Unknown Source)
    >         at org.python.core.ImportFunction.load(Unknown Source)
    >         at org.python.core.ImportFunction.__call__(Unknown Source)
    >         at org.python.core.PyObject.__call__(Unknown Source)
    >         at org.python.core.__builtin__.__import__(Unknown Source)
    >         at org.python.core.imp.importFromAs(Unknown Source)
    >         at org.python.core.imp.importFrom(Unknown Source)
    >         at org.python.pycode._pyx1.f$0(<iostream>:26)
    >         at org.python.pycode._pyx1.call_function(<iostream>)
    >         at org.python.core.PyTableCode.call(Unknown Source)
    >         at org.python.core.PyCode.call(Unknown Source)
    >         at org.python.core.Py.runCode(Unknown Source)
    >         at org.python.util.PythonInterpreter.execfile(Unknown Source)
    >
    > I've tried adding more paths to sys.path, with no luck:
    >
    > pySys.path.insert(0,new PyString("/path/to/myjar.jar/MyJar"));
    > pySys.path.insert(0,new PyString("file:jar:/path/to/myjar.jar!"));
    >
    > and nothing works, any ideas would help. I know this has to work,
    > because I previously had a problem where I couldn't do
    >
    > import os
    >
    > and then I added the "Lib/" folder inside jython.jar and now I'm able
    > to import all those standard jython modules, so, somehow, jython is
    > able to import .py within a .jar, help would be very much appreciated.
    >
    > Angel Leon
     
    Gubatron, Dec 3, 2008
    #2
    1. Advertising

  3. Gubatron

    Gubatron Guest

    Re: Jython: Packing several .py on .jar, problem importing .pymodules within the .jar

    cont...

    Take in consideration
    /** Hashtable of URLClassLoaders for each of the jars loaded */
    private Hashtable<String, URLClassLoader> classLoaders;

    Here's an example:

    org.python.core.PySystemState pySys = new
    org.python.core.PySystemState();

    //classLoaders is a set that refers to a bunch
    of URLClassLoader objects
    pySys.setClassLoader(((URLClassLoader)
    classLoaders.get(jarFile)));

    //We also have to pass the jar to JYTHON_PATH
    (sys.path)
    //so that it can properly import inner python
    modules.
    pySys.path.insert(0,new PyString(jarFile));

    //We pass the PythonInterpreter the modified
    PySystemState
    PythonInterpreter i = new PythonInterpreter
    (null, pySys);
    i.exec(pythonScriptName);


    Here's my method to create a classLoader that has a jarFile in its
    classpath:

    /**
    * Adds a given Jar to the Classpath.
    * Jython uses both classloaders, and it's JYTHONPATH (sys.path)
    * The classloaders help it find Java classes, in this case inside
    the jar
    * that contains the plugin.
    *
    * @param jarFile
    *
    * Where jarFile is the path (String) to the jarFile.
    *
    * I won't delete it though, in case it might be needed to load
    resources from
    * the jar. However, I believe the adition to the sys.path of jython
    will be enough.
    */
    public void addJar2Classpath(String jarFile) throws Exception {
    if (jarFile == null)
    throw new Exception("PluginLoader.addJar2Classpath() - the jar file
    path can't be null");

    File f = new File(jarFile);

    if (!f.exists()) {
    LOG.error("Jar doesn't exist ("+jarFile+")");
    throw new Exception("PluginLoader.addJar2Classpath() - The jar file
    doesn't exist ("+ jarFile +")");
    }

    URL jarURL = null;

    try {
    jarURL = new URL("jar:file:"+jarFile+"!/");
    //jarURL = f.toURI().toURL();
    LOG.info("The jar as an url " + jarURL);
    } catch (Exception e) {
    LOG.error("Bad URL for jar ("+jarFile+"):\n"+e.toString()
    +" ("+jarURL+")\n");
    return;
    }

    if (loadedJar(jarURL)) {
    LOG.info("Jar was already loaded ("+jarURL+")");
    return;
    }

    synchronized (classLoaders) {
    getLoadedJars().add((URL) jarURL);
    }

    //Create a new class loader for this jar.
    classLoaders.put(jarFile, URLClassLoader.newInstance(new URL[]
    {jarURL}));

    LOG.info("Jar loaded ("+jarURL+")");
    } //addJar2Classpath


    So if we had a Jar like this:

    M Filemode Length Date Time File
    - ---------- -------- ----------- --------
    -------------------------------------
    drwxrwxrwx 0 3-Dec-2008 12:46:22 meta-inf/
    -rw-rw-rw- 71 3-Dec-2008 12:46:22 meta-inf/manifest.mf
    drwxrwxrwx 0 3-Dec-2008 12:46:22 twoScriptsTest/com/
    -rw-rw-rw- 491 3-Dec-2008 12:46:22 twoScriptsTest/com/
    HelloFromJar.class
    drwxrwxrwx 0 3-Dec-2008 12:46:18 twoScriptsTest/guba/
    -rw-rw-rw- 0 3-Dec-2008 06:24:22 twoScriptsTest/guba/
    __init__.py
    -rw-rw-rw- 959 3-Dec-2008 12:46:18 twoScriptsTest/guba/
    test.py
    -rw-rw-rw- 124 2-Dec-2008 17:50:56 twoScriptsTest/guba/
    pleaseWork.py
    -rw-rw-rw- 0 3-Dec-2008 12:29:56 twoScriptsTest/
    __init__.py
    - ---------- -------- ----------- --------
    -------------------------------------

    When we executed:

    i.exec("from guba import test")

    if test.py had this code, it'd work perfectly:

    #Import and use the Java Object inside the jar
    from com import HelloFromJar
    h = HelloFromJar()
    h.sayHello()

    #Import the other python module inside the jar
    from pleaseWork import echo
    echo("FrostWire")


    NOTE: It's very important that you have the __init__.py on the folders
    otherwise Jython won't find the modules.

    On Dec 3, 12:54 pm, Gubatron <> wrote:
    > I've managed to solve this problem.
    >
    > I can now run a python script that lives inside a Jar. The python
    > script is now able to import other scripts within the same jar, and
    > it's also able to import java classes that live within the jar.
    >
    > The problem was solved by giving the Jython Interpreter the proper
    > initialization. This entails:
    >
    > - Giving it a class loader that has put the Jar on it's class path
    > - Adding the path of the jar to the interpreter's sys.path
    >
    > Here's an example:
    >
    >                         org.python.core.PySystemState pySys = new
    > org.python.core.PySystemState();
    >                         pySys.setClassLoader(((URLClassLoader) classLoaders.get(jarFile)));
    >
    >                         //We also have to pass the jar to JYTHON_PATH (sys.path)
    >                         //so that it can properly import inner python modules.
    >                         pySys.path.insert(0,new PyString(jarFile));
    >
    >                         //We pass the PythonInterpreter the modified PySystemState
    >                         PythonInterpreter i = new PythonInterpreter(null, pySys);
    >                         i.exec(pythonScriptName);
    >
    > On Dec 3, 6:31 am, Gubatron <> wrote:
    >
    > > Hello all,

    >
    > > I've a problem with Jython and importing .py inside a jar.

    >
    > > I'm putting .class and .py files inside .jar files.

    >
    > > myjar.jar
    > >   MyJar\SomeClass.class
    > >   MyJar\main.py
    > >   MyJar\otherModule.py

    >
    > > So I add the myjar.jar to Jython's sys.path

    >
    > >                         org.python.core.PySystemState pySys = new
    > > org.python.core.PySystemState();
    > >                         pySys.path.insert(0,new PyString("/path/to/myjar.jar"));

    >
    > > and execute main.py

    >
    > >                         //We pass the PythonInterpreter the modified PySystemState
    > >                         PythonInterpreter i = new PythonInterpreter(null, pySys);

    >
    > >                         //Find the entry in the jar for the python file and execute it.
    > >                         //It should be able to find any resource inside the jar.
    > >                         JarFile jFile = new JarFile("/path/to/myjar.jar");
    > >                         ZipEntry zipEntry = jFile.getEntry("MyJar/main.py");

    >
    > >                         InputStream pythonInputStream =
    > > jFile.getInputStream(zipEntry);
    > >                         i.execfile(pythonInputStream);

    >
    > > main.py will execute fine, it'll be able to do

    >
    > > from MyJar import SomeClass

    >
    > > with no problem

    >
    > > However, If I try to import the other .py in the same jar, it won't
    > > find it:

    >
    > > from otherModule import *

    >
    > > or

    >
    > > from MyJar.otherModule import *

    >
    > > I always get this:

    >
    > > ImportError: no module named otherModule

    >
    > >         at org.python.core.Py.ImportError(Unknown Source)
    > >         at org.python.core.imp.import_first(Unknown Source)
    > >         at org.python.core.imp.import_name(Unknown Source)
    > >         at org.python.core.imp.importName(Unknown Source)
    > >         at org.python.core.ImportFunction.load(Unknown Source)
    > >         at org.python.core.ImportFunction.__call__(Unknown Source)
    > >         at org.python.core.PyObject.__call__(Unknown Source)
    > >         at org.python.core.__builtin__.__import__(Unknown Source)
    > >         at org.python.core.imp.importFromAs(Unknown Source)
    > >         at org.python.core.imp.importFrom(Unknown Source)
    > >         at org.python.pycode._pyx1.f$0(<iostream>:26)
    > >         at org.python.pycode._pyx1.call_function(<iostream>)
    > >         at org.python.core.PyTableCode.call(Unknown Source)
    > >         at org.python.core.PyCode.call(Unknown Source)
    > >         at org.python.core.Py.runCode(Unknown Source)
    > >         at org.python.util.PythonInterpreter.execfile(Unknown Source)

    >
    > > I've tried adding more paths to sys.path, with no luck:

    >
    > > pySys.path.insert(0,new PyString("/path/to/myjar.jar/MyJar"));
    > > pySys.path.insert(0,new PyString("file:jar:/path/to/myjar.jar!"));

    >
    > > and nothing works, any ideas would help. I know this has to work,
    > > because I previously had a problem where I couldn't do

    >
    > > import os

    >
    > > and then I added the "Lib/" folder inside jython.jar and now I'm able
    > > to import all those standard jython modules, so, somehow, jython is
    > > able to import .py within a .jar, help would be very much appreciated.

    >
    > > Angel Leon

    >
    >
     
    Gubatron, Dec 3, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Taylor
    Replies:
    0
    Views:
    380
    John Taylor
    Oct 14, 2003
  2. David McNab
    Replies:
    0
    Views:
    522
    David McNab
    Apr 9, 2004
  3. Replies:
    2
    Views:
    412
  4. Divya Prakash
    Replies:
    0
    Views:
    469
    Divya Prakash
    Dec 19, 2006
  5. Pinegar, Kent T

    FW: [Jython-users] Jython Licensing Question

    Pinegar, Kent T, Jul 24, 2008, in forum: Python
    Replies:
    0
    Views:
    374
    Pinegar, Kent T
    Jul 24, 2008
Loading...

Share This Page