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.
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.