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

Gubatron gubatron at gmail.com
Wed Dec 3 13:01:54 EST 2008


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 <gubat... at gmail.com> 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 <gubat... at gmail.com> 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
>
>




More information about the Python-list mailing list