Code Monkey home page Code Monkey logo

jpy's Introduction

Build Status Documentation Status


‼️ We moved to jpy-consortium/jpy

jpy is now being further developed in a dedicated GitHub organision maintained by members of the companies DeepHaven and Brockmann Consult. This repo will soon be archived. Please use the new jpy-consortium/jpy for any issues or PRs, thanks!


jpy - a Python-Java Bridge

jpy is a bi-directional Python-Java bridge which you can use to embed Java code in Python programs or the other way round. It has been designed particularly with regard to maximum data transfer speed between the two languages. It comes with a number of outstanding features:

  • Fully translates Java class hierarchies to Python
  • Transparently handles Java method overloading
  • Support of Java multi-threading
  • Fast and memory-efficient support of primitive Java array parameters via Python buffers (e.g. Numpy arrays)
  • Support of Java methods that modify primitive Java array parameters (mutable parameters)
  • Java arrays translate into Python sequence objects
  • Java API for accessing Python objects (jpy.jar)

jpy has been tested with Python 3.4–3.8 and OpenJDK 8 on 64-bit Ubuntu Linux, Windows 10, and macOS.

The initial development of jpy was driven by the need to write Python extensions to an established scientific imaging application programmed in Java, namely the SNAP toolbox, the SeNtinel Application Platform project, funded by the European Space Agency (ESA). (jpy is bundled with the SNAP distribution.)

Writing such Python plug-ins for a Java application usually requires a bi-directional communication between Python and Java since the Python extension code must be able to call back into the Java APIs.

For more information please have a look into jpy's

How to build wheels for Linux and Mac

Install a JDK 8, preferably the Oracle distribution. Set JDK_HOME or JPY_JDK_HOME to point to your JDK installation and run the build script:

$ export JDK_HOME=<your-jdk-dir>
$ export JAVA_HOME=$JDK_HOME
$ python setup.py build maven bdist_wheel

On success, the wheel is found in the dist directory.

To deploy the jpy.jar (if you don't know why you need this step, this is not for you)::

$ mvn clean deploy -DskipTests=true

How to build a wheel for Windows

Set JDK_HOME or JPY_JDK_HOME to point to your JDK installation. You'll need Windows SDK 7.1 or Visual Studio C++ to build the sources. With Windows SDK 7.1::

> SET VS90COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\
> SET DISTUTILS_USE_SDK=1
> C:\Program Files\Microsoft SDKs\Windows\v7.1\bin\setenv /x64 /release
> SET JDK_HOME=<your-jdk-dir>
> python setup.py build maven bdist_wheel

With Visual Studio 14 and higher it is much easier::

> SET VS100COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\
> SET JDK_HOME=<your-jdk-dir>
> python setup.py build maven bdist_wheel

On success, the wheel can be found in the dist directory.

How to install from sources

TBD

Releasing jpy

The target reader of this section is a jpy developer wishing to release a new jpy version. Note: You need to have Sphinx installed to update the documentation.

  1. Make sure all Java and Python units tests run green
  2. Remove the -SNAPSHOT qualifier from versions names in both the Maven pom.xml and setup.py files, and update the version numbers and copyright years in jpyutil.py and doc/conf.py.
  3. Generate Java API doc by running mvn javadoc:javadoc which will update directory doc/_static
  4. Update documentation, cd doc and run make html
  5. http://peterdowns.com/posts/first-time-with-pypi.html

Automated builds

As of 2020-08-27, Python wheel packages for jpy are automatically built on AppVeyor, but at present they are uploaded only to a private FTP server and not publicly released. Wheels are built for Python versions 3.4, 3.5, 3.6, 3.7, and 3.8 on Linux, Windows, and macOS (≥10.9). Only 64-bit wheels are built.

The repository also contains an outdated configuration for automated Travis builds, but this configuration is currently unmaintained and broken.

jpy's People

Contributors

chipkent avatar cpwright avatar davidlehrian avatar dependabot[bot] avatar desruisseaux avatar devinrsmith avatar dr-irv avatar forman avatar gbaier avatar heptaflar avatar marpet avatar mzuehlke avatar olgafaber avatar pont-us avatar thomasstorm avatar voutilad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jpy's Issues

Deploy jpy OSGi bundle

The jpy JAR should be deployed as an OSGi bundle.
Check: how to deal with native code linked against Python / C API?

This is very important for the upcoming Sentinel Toolbox development.

Allow jpy Java API to work with multiple Python installations

The Java API looks up the (native) jpy Python module from a hidden file $HOME/.jpy. This file contains a link to the jpy shared library, respectively installed by the last jpy setup.
If users have multiple Python installations (e.g. versions 2.7/3.4 or 32-bit / 64-bit platforms), the Java API is unable to locate these as there is currently no configuration parameter for that.

We could either add a parameter to PyLib.startPython() or use a naming pattern for the $HOME/.jpy file, so that the Java PyLib class can select the appropriate Python interpreter interpolated from the JRE architecture and Python version, e.g. ".jpy-py27-amd64".

The current workaround is to simply edit the $HOME/.jpy file to make it point to the wanted jpy Python shared library file.

array.fromstring('str', 'int') and array.tostring()

Hi forman:

b = jpy.array('int', [1,2,3])
b.toString()
'[I@3f2a09d5'

But what I want to do is if I got string '[I@3f2a09d5', is it possible to get [1,2,3]. I have spent a lot of time on this, appreciate for your help!

jpy.array should also accept initializer

jpy.array(type | type_name, length) ==>

jpy.array(type | type_name, length | initializer)

with initializer being any buffer or sequence (array, list, tuple, ...)

How to remove a loaded module

Hi,

I have loaded a script (module) into Python Interpreter using the below

PyModule.extendSysPath(Path_to_Script, true);
PyModule.importModule(Script_Name)

Now I have to remove this module.
How can I do this?
Is there any function in C-API?

Thanks a lot.

Compile error on OS X with Python 3.4

Installing jpy on OS X with Python 3.4 gives the following compile error:

src/main/c/jni/org_jpy_PyLib.c:793:42: error: passing 'PyObject'
(aka 'struct _object') to parameter of incompatible type 'PyObject _'
(aka 'struct _object *'); remove *
chars = PyBytes_AsString(_pyObjUtf8);

Python crash with multiple JVM threads

The Python interpreter crashes when we call from multiple JVM threads at the same time. See

  • PyObjectTest.testCreateProxyAndCallSingleThreaded() --> ok
  • PyObjectTest.testCreateProxyAndCallMultiThreaded() --> crash

It is for sure a GIL-related bug. Look here for very similar problems:

Jpy in Multi-Thread Based Application

HI Norman,

Please suggest us as we are facing few Memory issues with usage of jpy in our application.

Context

We are building an Mutli-Language(Script oriented), distributed and muti-threading application in Java and we need to run user Python Scripts from our application (Application also supports R, Groovy).

One functionality flow in our application is that,

  1. any can user uploads a python script and intimate the application to publish his python script, the script is loaded and run by a thread and here we are using jpy to handle User Python Scripts related tasks.
  2. Now user can kill any thread (meaning, stop his running script) make modifications to it and reload the scripts to application and run them (basically with new threads)

what we have observed is, as user kills and publishes new threads, JVM memory is handled with out any hassle but since I have no way to cleanup the loaded modules and since user uses memory extensive modules like opencv etc, the memory is summing up to an extent where eventually at some point in time application is crashing with memory crunch.

Could you please suggest a right approach to use jpy in this context or is this rite use-case to use jpy?

Thanks in advance.

Java primitive arrays occasionally not initialised by Python buffers

The following problem may or may not occur::

Running src/test/python/jpy_typeconv_test.py
..F
======================================================================
FAIL: test_ToPrimitiveArrayConversion (__main__.TestTypeConversions)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "src/test/python/jpy_typeconv_test.py", line 32, in test_ToPrimitiveArrayConversion
    self.assertEqual(fixture.stringifyIntArrayArg(a), 'int[](1,2,3)')
AssertionError: 'int[](0,0,0)' != 'int[](1,2,3)'
- int[](0,0,0)
?       ^ ^ ^
+ int[](1,2,3)
?       ^ ^ ^

The test code is::

def test_ToPrimitiveArrayConversion(self):
    fixture = self.Fixture()

    # Python int array to Java int array
    a = array.array('i', [1,2,3])
    self.assertEqual(fixture.stringifyIntArrayArg(a), 'int[](1,2,3)')
    ...

Java (primitive array) parameters can be mere outputs

jpy can avoid copying memory from Python buffers to Java primitive array parameters if the parameter is known to be a mere output value of the method (and not read from by the method).

This would make Java method calls with mutable primitive array parameters more efficient.

Lazily create JVM

We currently must explicitely call

jpy.create_jvm(jvm_options)

before we can import Java classes. To avoid this,

  • we could let users provide 'jvm_options' in an INI file that is optionally loaded when the JVM is implictely created;
  • or we load and execute a user defined 'jpy_conf.py' in order (to construct) to obtain 'jvm_options'.

For the latter, refer to PyRun_String as described here
http://docs.python.org/3/c-api/veryhigh.html?highlight=pyrun_string#PyRun_String

Another (or additional) possibility:

import jpy
jpy.jvm_options = ['-Xmx512M', '-Djava.class.path=target/classes']

jpy.jvm_options can be directly evaluated in the jpy C code before the JVM is implicitely created.

Python extensions loaded from Java can't see Python symbols (Linux)

The following problem occurred on Linux (Ubuntu 12.04) when invoking the Python interpreter from Java (here from a BEAM extension module):

numpy-bug

The Python extension 'numpy' obviously doesn't know about Python anymore when the Python interpreter is loaded from Java and the interpreter again loads numpy. Note that PyExc_SystemError is a symbol defined in practically all Python shared library versions.

On Windows, this works perfectly.

Provide compatibility with Python 3.2

For example, the 3.3 function PyUnicode_AsUTF8() can be replaced as follows:

   PyObject* pyUTF8 = PyUnicode_AsEncodedString(pyUnicode, "utf-8", "replace");
   char* chars = PyBytes_AsString(pyUTF8);
   ...
   Py_DECREF(pyUTF8);

Simplify jpy installation

The installation process of jpy is too complicated and too prone to configuration errors.

This is mainly due to compilation of C and Java sources. Especially the C compilation on Windows is not straight forward. For Windows users, we could generate installers for Python 2.7/3.3/3.4 for both 32 and 64bit executables.They install the jpy Python module (shared library), copy the jpy.jar and write/modify the %HOME%.jpy file and ask for the JRE (or JVM shared library) location.

Users currently must also ensure that the parent directory of a compatible JVM shared library (libjvm.so on Unix, jvm.dll on Windows) is part of the LD_LIBRARY_PATH (Unix) or PATH (Windows) environment variable, so that it can be loaded by the jpy Python module. This step should be avoided or at least simplified, if somehow possible. Note that changing LD_LIBRARY_PATH or PATH from Python has no effect but maybe adding the JVM directory path using sys.path.append(jvm_dir) helps (see http://stackoverflow.com/questions/856116/changing-ld-library-path-at-runtime-for-ctypes) .

Other improvement ideas:

  • We don't force users to compile Java at all. We simply bundle a precompiled jpy.jar in the source and binary distributions.
  • Avoid setting JAVA_HOME env var: It could be set to JDK_HOME before os.system('mvn ...') is called: os.environ['JAVA_HOME'] = os.environ['JDK_HOME']

Convert to actual type instead of Object

There is a problem with Java collections which all return java.lang.Object items, because Java generic type information is not available at runtime.

So before we convert to a corresponding Python value, we must inferr the actual Object type, beacause usually the Object value is meaningless to Python programmers (unless such values are passed through as arguments to other Java method calls).

In WSGI environment, jpy crashes when instantiating new object

In an Apache WSGI environment, jpy crashes when a new object is instantiated using the constructor. For example, the following chain of commands fails:

File = jpy.get_type('java.io.File')
File('somePath')

The first lines of the stacktrace read:

*** glibc detected *** /opt/apache2/bin/httpd: free(): invalid pointer: 0x00007fcb5a1435e0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fcb712d3b96]
/usr/local/lib/python2.7/dist-packages/jpy.so(JPy_AsJString+0x93)[0x7fcb59f30e63]
/usr/local/lib/python2.7/dist-packages/jpy.so(JMethod_CreateJArgs+0x133)[0x7fcb59f38983]
/usr/local/lib/python2.7/dist-packages/jpy.so(JObj_init+0xa5)[0x7fcb59f374a5]
/usr/lib/libpython2.7.so.1.0(+0x142108)[0x7fcb6dbaf108]
/usr/lib/libpython2.7.so.1.0(PyObject_Call+0x53)[0x7fcb6dbae083]
/usr/lib/libpython2.7.so.1.0(PyEval_EvalFrameEx+0x3fcd)[0x7fcb6db081fd]
/usr/lib/libpython2.7.so.1.0(PyEval_EvalCodeEx+0x855)[0x7fcb6dac96b5]

The same chain of commands runs perfectly fine in a regular python shell.

Add diagnostic levels

We currently use the debug flag to switch on verbose mode. This is not useful because we dump to many stuff at once. We need a finer control, e.g.

  • off=0
  • all=0xff
  • mem=0x01 // Python memory alloc/dealloc for Java objects
  • type=0x02 // Java type resolution
  • call=0x04 // calling of Java methods, Java field access
  • meth=0x10 // finding matching Java methods

Unwrap Java objects (PyObject) passed to PyLib methods

Use case: Extend Python by Java code.

We must unwrap Java objects (PyObject) passed to PyLib methods to obtain Python object pointers (PyObject*). Otherwise we cannot callback into Python when we call Java from Python and use the jpy Java API in our Java code.

Resolve unresolved Java types once one of its methods is called

Example:
group = product.getFlagCodingGroup()
group.add(FlagCoding('quality_flags'))

The first statement returns an ProductNodeGroup, If this class has not been resolved, e.g. via a call to jpy.get_class('org.esa.beam.framework.datamodel.ProductNodeGroup'), it's 'add' method remains unknown.

error running maven tests on master

Am I doing something wrong?

When running mvn clean install I get the below error (after successful 64-bit python setup.py install) but it doesnt say what the missing dependent libraries are. Not sure at all what to do here?

org.jpy.PyLibTest Time elapsed: 0.001 sec <<< ERROR!
java.lang.UnsatisfiedLinkError: C:\workspaces\jpy\build: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1929)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1814)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1083)
at org.jpy.PyLib.loadLib(PyLib.java:352)
at org.jpy.PyLib.(PyLib.java:366)
at org.jpy.PyLibTest.setUpClass(PyLibTest.java:27)

this is after i changed the code that was occurring in my other issue about compiling with 1.8.

in pyobject:

public void setAttribute(String name, Object value) {
    assertPythonRuns();
    Class clazz;
    if (value != null) {
        clazz = value.getClass();
    } else {
        clazz = null;
    }
    PyLib.setAttributeValue(getPointer(), name, value, clazz);
}

also had to add this otherwise got the below exception:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.18.1</version>
                <configuration>
                    <systemPropertyVariables>
                        <jpy.jpyLib>C:\app\python\Lib</jpy.jpyLib> 
                    </systemPropertyVariables>
                </configuration>
            </plugin>


java.lang.ExceptionInInitializerError: null
        at org.jpy.PyLibConfig.getProperty(PyLibConfig.java:117)
        at org.jpy.PyLib.loadLib(PyLib.java:345)
        at org.jpy.PyLib.<clinit>(PyLib.java:366)
        at org.jpy.PyLibTest.setUpClass(PyLibTest.java:27)


python setup final output was:

OK
JPy_free: freeing module data...
JPy_free: done freeing module data
setting environment variable 'PYTHONPATH' to None
jpy binary build is 'build\jpy.win-amd64-3.4.zip'
jpy installed into 'C:\app\python\Lib\site-packages\'

Use 'import' to import Java classes

We want to use

from java.io import File

We currently must use

File = jpy.get_class('java.io.File')

Add a new module function 'import' which calls 'get_class' but then creates new modules up the last dot in the class name. E.g. java.io.File will create the module 'java', than create 'io' and add this to 'java' and then add class 'File' to 'io'.

Add missing support for Java non-final static fields

See TODOs in jpy_jobj.c:

implement a special lookup: we need to override getattro of JType (--> JType_getattro) as well so that we know if a method is called on a class rather than on an instance. Using PyObject_GenericGetAttr will also call JType_getattro, but then we loose the information that a method is called on an instance and not on a class.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.