开发者

Jython CLASSPATH, sys.path and JDBC drivers

How can I add JDBC drivers at runtime to Jython? Using CLASSPATH works, but using sys.path doesn't work with zxJDBC even though the class is imported fine and can be manipulated from the Jython interpreter prompt.

Why does this work:

$ CLASSPATH=/tmp/jtds\-1.2.5.jar ./jython
*sys-package-mgr*: processing new jar, '/private/tmp/jtds-1.2.5.jar'
Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) 
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20
Type "help", "copyright", "credits" or "license" for more information.
>>> from java.lang import Class
>>> Class.forName('net.sourceforge.jtds.jdbc.Driver')
<type 'net.sourceforge.jtds.jdbc.Driver'>

But this doesn't?

$ ./jython

Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) 
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.extend(['/tmp/jtds-1.2.5.jar'])
>>> from java.lang import Class
>>> Class.forName('net.sourceforge.jtds.jdbc.Driver')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)

java.lang.ClassNotFoundException: java.lang.ClassNotFoundException: net.sourceforge.jtds.jdbc.Driver
>>> sys.path
['', '/home/me/pkg/jython2.5.1/Lib/site-packages/distribute-0.6.13-py2.5.egg', '/home/me/pkg/jython2.5.1/Lib', '__classpath__', '__pyclasspath__/', '/home/me/pkg/jython2.5.1/Lib/site-packages', '/home/me/pkg/jython2.5.1/Lib/site-packages/setuptools-0.6c11-py2.5.egg-info', '/tmp/jtds-1.2.5.jar']
>>> import net.sourceforge开发者_如何学Python.jtds.jdbc.Driver as Driver
>>> drv = Driver()
>>> drv
jTDS 1.2.5

Does it have something to do with the classloader?


Looks like even the updated link does not work anymore (at least with jython-2.5.3b3).

Here's a working version:

def importJar(jarFile):
    '''
    import a jar at runtime (needed for JDBC [Class.forName])

    adapted from http://forum.java.sun.com/thread.jspa?threadID=300557
    Author: SG Langer Jan 2007 translated the above Java to Jython
    Author: seansummers@gmail.com simplified and updated for jython-2.5.3b3

    >>> importJar('jars/jtds-1.2.5.jar')
    >>> import java.lang.Class
    >>> java.lang.Class.forName('net.sourceforge.jtds.jdbc.Driver')
    <type 'net.sourceforge.jtds.jdbc.Driver'>
    '''
    from java.net import URL, URLClassLoader
    from java.lang import ClassLoader
    from java.io import File
    m = URLClassLoader.getDeclaredMethod("addURL", [URL])
    m.accessible = 1
    m.invoke(ClassLoader.getSystemClassLoader(), [File(jarFile).toURL()])

if __name__ == '__main__':
    import doctest
    doctest.testmod()

I keep this Gist updated with my production version.


The solution is tricky, but everything is explained here.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜