Python4J Cannot find the customized Python path in miniconda

Dear Community,

Recently, I’m trying to integrate my Pytorch models in the DL4J environment. Since my Pytorch models require additional modules, I need to create a virtual environment to import all dependencies.

As shown in the section Python Path in DL4J, DL4J enables the users to customize their own python environments. I created the new python virtual environment with miniconda. Unfortunately, I do not understand the following points:

  • org.eclipse.python4j.path: Should I change this path? As I understood, The user should use the following codes to get the path info:

import sys
import os
print(os.pathsep.join(sys.path))

I created a virtual environment for python 3.10.4. However, using the code above, the python version turns to be python 3.10.2. After inspecting the deep4j project, I found that the printed version is the one that is automatically loaded and cached by the deep4j framework (javacpp) within the CPython-3.10.2.xxx.jar.

In such a case, how to let the D4J project accept the newly created virtual environment?

  • org.eclipse.python4j.path.append: How can I use this property concretely? What does the following explanation mean? Further information or a demo would be great. What do the “none, before, after” imply here? How to use these flags?
A user can select none, before, or after.
In order to specify a custom python path, a user should be aware of 3 properties
  • Eager graph (TensorFlow 2.x eager/PyTorch) graph execution is planned. Is there any release plan for this supportive feature available now?

I’m working with Eclipse. Any further information & input about integrating the Pytorch model into DL4J will be appreciated.

Thanks in advance!

@Anakin that just gets you the python path you still have to set the system property. The append type just sets whether we should use any of the pre built in libraries (numpy mainly) or if we should let the user specify.

Hi @agibsonccc thanks a lot for your response and the explanation. I’m still a little bit confused by these preperties. Here is the Java snippet:

public class PythonExecutor {
	public static void main(String[] args) throws InterruptedException {
			System.setProperty("org.eclipse.python4j.path.append", "/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python310.zip:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python3.10:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python3.10/lib-dynload:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python3.10/site-packages");
			System.out.println("org.eclipse.python4j.path.append " + System.getProperty("org.eclipse.python4j.path.append"));
	
			try (PythonGIL pythonGIL = PythonGIL.lock()) {
				
				List<PythonVariable> inputs = new ArrayList<PythonVariable>();
				String code = Files.readString(Paths.get("/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/hello_python2.py"));
				
				PythonExecutioner.exec(code);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
    }
}

The python script is shown as follows:

import os
import sys
from platform import python_version

print('path:{}'.format(os.pathsep.join(sys.path)))

print('python_version', python_version())

import torch
import torchvision

After running the Java code, I got the following error:

org.eclipse.python4j.path.append /home/skywalker/miniconda3/envs/venv_dl4j_3.10.4:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python310.zip:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python3.10:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python3.10/lib-dynload:/home/skywalker/miniconda3/envs/venv_dl4j_3.10.4/lib/python3.10/site-packages
12:13:38.371 [main] DEBUG org.nd4j.python4j.PythonGIL - Acquiring GIL on 1
12:13:38.373 [main] INFO org.nd4j.python4j.PythonGIL - Pre Gil State ensure for thread 1
12:13:38.373 [main] INFO org.nd4j.python4j.PythonGIL - Thread 1 acquired GIL
Traceback (most recent call last):
  File "<string>", line 65, in <module>
ModuleNotFoundError: No module named 'torch'
path:/home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib:/home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/site-packages:/home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/python3.10:/home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/python3.10/lib-dynload:/home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/python3.10/site-packages:/home/skywalker/.javacpp/cache/numpy-1.22.2-1.5.7-linux-x86_64.jar/org/bytedeco/numpy/linux-x86_64/python
0 /home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib
1 /home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/python3.10
2 /home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/python3.10/site-packages
sys.path:/home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/site-packages:/home/skywalker/.javacpp/cache/cpython-3.10.2-1.5.7-linux-x86_64.jar/org/bytedeco/cpython/linux-x86_64/lib/python3.10/lib-dynload:/home/skywalker/.javacpp/cache/numpy-1.22.2-1.5.7-linux-x86_64.jar/org/bytedeco/numpy/linux-x86_64/python
python_version 3.10.2
No module named 'torch'
12:13:38.384 [main] DEBUG org.nd4j.python4j.PythonGIL - Pre gil state release for thread 1
12:13:38.385 [main] INFO org.nd4j.python4j.PythonGIL - Releasing GIL on thread 1
org.nd4j.python4j.PythonException: ModuleNotFoundError: No module named 'torch'
	at org.nd4j.python4j.PythonExecutioner.throwIfExecutionFailed(PythonExecutioner.java:201)
	at org.nd4j.python4j.PythonExecutioner.exec(PythonExecutioner.java:229)
	at com.demo.PythonExecutor.main(PythonExecutor.java:111)

It turns out that although the append property is set (not sure, whether it has been done correctly), the javacpp stills calls the pre-built python, i.e., cpython-3.10.2.xxx.jar, in which the torch is not installed yet.

In my case, there are multiple Pytorch models, converting these models with onnx is much more daunting work since there are different issues during the exporting. As a short term solution, therefore I intent to use all the existing python-based solutions diretly and wait until D4J framework releases the powerful features for (eager/PyTorch) graph. Is it necessary to activate the miniconda environment at first within D4J?

I’m still struggling with this issue to use this customized python environment in D4J ecosystem. Any inputs will be appreciated.

@Anakin python4j doesn’t really understand miniconda concepts. You have to activate the right profile in miniconda then use the python script to get the right python path. All we can do is load a python path you tell us to.
I think you should isolate anything to do with python4j specifically and first just understand what a python path is and how it works. Googling brings this up:

Once you understand what a PYTHONPATH is the properties we list make a bit more sense.

Beyond that…I’m not sure what the issue is with onnx models. I’d at least try it. It’s just a few lines of code. You can see some examples here: deeplearning4j/pytorch.py at master · eclipse/deeplearning4j · GitHub

It’s basically just setting up the data in pytorch and then calling export. That export call traces the call graph and sets up the appropriate ops. I’m happy to support either use case though.