Jython CLASSPATH, sys.path and JDBC drivers

可紊 提交于 2019-11-27 01:58:23

问题


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.jtds.jdbc.Driver as Driver
>>> drv = Driver()
>>> drv
jTDS 1.2.5

Does it have something to do with the classloader?


回答1:


The solution is tricky, but everything is explained here.




回答2:


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.



来源:https://stackoverflow.com/questions/3015059/jython-classpath-sys-path-and-jdbc-drivers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!