theskumar / python-dotenv

Reads key-value pairs from a .env file and can set them as environment variables. It helps in developing applications following the 12-factor principles.
https://saurabh-kumar.com/python-dotenv/
BSD 3-Clause "New" or "Revised" License
7.7k stars 431 forks source link

Cannot import dotenv module when python file runs by java. #495

Closed kavicastelo closed 11 months ago

kavicastelo commented 11 months ago

This script contains in my springboot application. when I send the request to the run this script it will automatically runs. I used this method to run python file from java. Used py4j library to make connection between java and python.

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;
            }

            // Execute the command
            Process process = Runtime.getRuntime().exec(command);

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

            // Read the error output from the Python script
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            while ((line = errorReader.readLine()) != null) {
                System.err.println(line);
            }

            // Wait for the Python script to finish
            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):
        # Connect to the Py4J gateway server
        self.gateway = JavaGateway()

        # Retrieve the Java instance of the model
        self.java_model = self.gateway.entry_point

        # Load the PMML model
        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)

            # Perform prediction using the loaded model
            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 the prediction
            return prediction
        except Exception as e:
            # Handle any errors during prediction
            return str(e)

if __name__ == "__main__":
    load_dotenv()
    # Create an instance of the Python class
    air_humidity_model = AirHumidityModelPython()
    # test data
    # 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, user sends the values array to the springboot backend then springboot service runs the first method. it will run the python file. Then it makes the prediction and sends predicted value to the springboot backend again. springboot cache the python requested value and sends it to the user as a response.

The problem is dotenv occurs this error when runs the file

import dotenv
ModuleNotFoundError: No module named 'dotenv'

This is not happennig when directly run the python file. It happens when python file automatically runs

kavicastelo commented 11 months ago

Problem Solved! The error occurs because python-dotenv package cannot import when python.exe and lib are in separate locations. Here is the solution