pythonjavaspringenvironment-variablespython-dotenv

Why cannot import `dotenv-python` module when the python file runs from Java?


This script is contained in my Spring Boot application. when I send the request to run this script it will automatically run. I used the py4j library to make the connection between Java and Python. I used this method to run Python files from Java.

public void runScript(String file){
        try {
            String pythonScriptPath = "./src/main/java/com/api/air_quality/python/" + file + ".py";
            String pythonExecutablePath = "C:\\Users\\KAVI\\AppData\\Local\\Programs\\Python\\Python310\\python.exe";
            String command = pythonExecutablePath + " " + pythonScriptPath;

            // Append the cached data to the command
            for (Double value : airQualityDataCache.get()) {
                command += " " + value;
            }

            Process process = Runtime.getRuntime().exec(command);

            // output
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // error
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            while ((line = errorReader.readLine()) != null) {
                System.err.println(line);
            }

            int exitCode = process.waitFor();
            if (exitCode != 0) {
                System.out.println("Python script exited with code: " + exitCode);
            }

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

This is the python file I want to add .env variables.

from time import sleep
from dotenv import load_dotenv
from py4j.java_gateway import JavaGateway
import numpy as np
import pickle
import sys
import requests
import os
# to ignore warnings
import warnings
warnings.filterwarnings('ignore')


class AirHumidityModelPython:
    def __init__(self):
        self.gateway = JavaGateway()
        self.java_model = self.gateway.entry_point

        with open("./AI_Models/airHumidity_model.pkl", 'rb') as f:
            self.model = pickle.load(f)

    def predict_air_humidity(self, features):
        try:
            features_2d = np.array(features).reshape(1, -1)
            prediction = self.model.predict(features_2d)[0]

            url = os.getenv("SPRINGBOOT_URL_PYTHON")
            spring_boot_url = url+"/airHumidity"

            # Send the prediction to the Spring Boot endpoint
            response = requests.post(spring_boot_url, json=float(prediction))
            # print(response.text)

            return prediction
        except Exception as e:
            # Handle any errors during prediction
            return str(e)


if __name__ == "__main__":
    load_dotenv()
    # instance
    air_humidity_model = AirHumidityModelPython()
    
    # dummy_features = [[1.5, 2.3, 4.2, 5.1, 7.7, 9.4, 10.0]]
    data_from_java = [float(arg) for arg in sys.argv[1:]]
    result = air_humidity_model.predict_air_humidity(data_from_java)
    # result = air_humidity_model.java_model.Message()

The workflow is in this case, the user sends the values array to the springboot backend then the springboot service runs the above first method. it will run the Python file. Then it makes the prediction and sends the predicted value to the springboot backend again. Spring Boot caches the Python requested value and sends it to the user as a response.

The problem is python-dotenv occurs this error when runs the file

import dotenv
ModuleNotFoundError: No module named 'dotenv'

I installed the correct python-dotenv library into my project using the following command. I'm using Python 3.10.4

pip3 install python-dotenv

also tried,

pip3.10 install python-dotenv

this too.

pip3 uninstall -U python-dotenv

Then I ran the Python file directly without involving Java and it worked fine.

The error occurs only when a Python file runs through the Java method. Other Python imports don't make any errors.


Solution

  • This error occurs because I loaded the python.exe from the device drive and the lib folder from the root venv. When I'm trying to execute the Python file from Java, It can't load some activation-needed libraries. The reason is executer and library are in separate locations. So I modified a few things in my code. In python file,

    venv_path = "../../../../../../../venv"
    sys.path.append(venv_path + '/Lib/site-packages')
    

    I appended the environment venv folder path as a system path. Now this file path works as it came from the system.

    in java method,

    String venvPath = "./venv";
    String pythonExecutablePath = venvPath + "/Scripts/python.exe";
    String pythonScriptPath = "./src/main/java/com/api/air_quality/python/" + file + ".py";
    String command = pythonExecutablePath + " " + pythonScriptPath;
    

    I changed the python executable path as gets from the venv root folder also. Now this code works fine and it will not get any problems in it's deployment too.