0
votes

i have a Python file that has a ML model in it and it is working perfectly when i run it separately from cmd.

i am currently trying to run it from node whenever i post on a specific route.

But, till now, i have failed to run the python script.

I have used two modules in node till now, I have used child_process and i have also used @fridgerator/pynode.

1- The problem arising with @fridgerator/pynode is that its constantly giving the error, ModuleNotFoundError: No module named 'team_match_prediction3' Failed to load module: team_match_prediction3

team_match_prediction3 is the python file name which i have placed along with the node.js file :

Following is the code of the Node.js route with the @fridgerator/pynode module :

router.post(("/team"),(req, res) =>
{

let regressionModel = {};
pynode.startInterpreter();
pynode.appendSysPath('./');
pynode.openFile('team_match_prediction3');
    let team_1 = req.body.Team1;
    let team_2 = req.body.Team2;

    new Promise((resolve, reject) => {
        try {
          if (_.isEmpty(regressionModel)) {
            console.log('calling python');
            regressionModel = pynode.call('starting_func',team_1, team_2);
          }
          resolve(regressionModel);
        } catch(err) {
          console.log(err);
          reject('failed to load Teams variables');
        }
    })
    .then(response => res.send(response))
    .catch(err => res.err(err));


});

i found this pynode code snippet from this website : https://thecodinginterface.com/blog/bridging-nodejs-and-python-with-pynode/

2- Then i used the child process module, the problem that arose with that module was that, the stdout.on("data") method wasn't running and it wouldn't even wait for the python script to finish and just run the python.on('close') function.

This is the node.js code for the child_process part:

//The import 
const {spawn} = require('child_process');


router.post(("/team"),(req, res) =>
{
 let team_1 = req.body.Team1;
    let team_2 = req.body.Team2;


    const python = spawn('python', ['./team_match_prediction3.py' , team_1,team_2]);
    let dataToSend = [];
    python.stdout.on('data', (data) => {
        console.log('Pipe data from python script ...');
        dataToSend.push(data);
       });
    
       // in close event we are sure that stream from child process is closed
        python.on('close', (code) => {
            console.log(`child process close all stdio with code ${code}`);
            // send data to browser
            res.send(`THis is result : ${dataToSend}`);
            });

when i use the child process module, it just gives a console.log that process ended with pid 2, this happens almost immediately, and sends no data as response.

Regarding the python file, for the pynode module, i just created a function to be called by pynode that just calls the clean_and_predict function which just returned the data required,

But when i use child process, i just do this at global level in the python file:


team_1 = sys.argv[1]
team_2 = sys.argv[2]


semi = [(team_1,team_2)]
clean_and_predict(semi, ranking, final, rf)

and the clean_and_predict function does its working and at the end, just prints out the required data and i do :

print(final_answer["Winner"])
sys.stdout.flush()

final_answer is a dict, with Winner, having the name of winning cricket team.

Any idea on how to fix this or if a new module should be used would be appreciated, thanks.

1

1 Answers

0
votes

i was able to solve this problem, firstly i partially solved the file not found error by providing path from the folder where the server.js file was stored instead of the router file calling the python file.

The other problem was waiting for the python file to execute and getting a result from it, i used the npm module execa to do this,

This is the part of the node that calls and waits for the python file:


    const execa = require('execa');

Then in the post route:


      
let team_1 = req.body.Team1;
let team_2 = req.body.Team2;


  const subprocess = execa('python 
path/to/pythonfile/from/serve.js/folder', [team_1,team_2]);
  subprocess.stdout.pipe(process.stdout);

  (async () => {
    const {stdout} = await subprocess;
    // Returning Result: 
    res.send(stdout);
    console.log('child output:', stdout);
})();