Search code examples
javascriptpythonchild-process

How to create a generalized JavaScript function that can run python scripts and return data in json format if any?


What I am currently able to do

const { spawn } = require("child_process");

exports.fetchWeatherdata = (location) => {
  console.log("DIR NAME DB" + __dirname)
  return new Promise((resolve, reject) => {
    let buf = "";
    const python = spawn("python", [
      __dirname + "/weathergetter.py",
      location.toString(),
    ]);

    python.stdout.on("data", (data) => {
      buf += data;
    });

    python.stderr.on("data", (data) => {
      console.error(`stderr: ${data}`);
    });

    python.on("close", (code) => {
      if (code !== 0) {
        return reject(`child process died with ${code}`);
      }
      const dataToSend = JSON.parse(buf.toString().replace(/\'/g, '"'));
      return resolve(dataToSend);
    });
  });
};


//in another file
const { fetchWeatherdata } = require('../python/weather')
exports.sendData = (req, res) => {
    console.log(req.query)
    console.log(req.params)

    async function main() {
        var wea = await fetchWeatherdata(req.params.loc);
        // console.log(wea);
        res.send(wea)
    }
    main()
}



What I want to achieve

const { spawn } = require("child_process");

exports.pythonFileRunner = (pathToFile, arguments) => {
   // some code goes here. This is where I need help
   return "output of the python file 📂"
}

//in another file
const { pythonFileRunner } = require('../python/weather')

exports.fetchWeatherdata = (location) => {
   //something like this ↓↓↓
   data = pythonFileRunner("path/to/file/main.py", location)
   return data
}

Basically, I want to create a function that can run any given python file with or without arguments and return its output.
Please Note: I want to finish all the async-await stuff inside the pythonFileRunner() function. This function must return only the output, which I can modify according to my usecase

If I am taking the wrong approach, please let me know in the comments.


Solution

  • I have modified the fetchweatherdata function little to get what I wanted.

    const { spawn } = require("child_process");
    
    function pythonRunner(path, arguments) {
        return new Promise((resolve, reject) => {
            let buf = "";
            arguments.unshift(path)
            const python = spawn("python", arguments);
        
            python.stdout.on("data", (data) => {
              buf += data;
            });
        
            python.stderr.on("data", (data) => {
              console.error(`stderr: ${data}`);
            });
        
            python.on("close", (code) => {
              if (code !== 0) {
                return reject(`child process died with ${code}`);
              }
              const dataToSend = buf
              return resolve(dataToSend);
            });
          });
    }
    
    
    
    //in any other file
    //first import the function
    
    //how to use the function
    (async () => {
      data = await pythonRunner("path/to/python/file", ["arg1", "arg2"])
      console.log(data)
    })()