Run Python script from Node.js using child process spawn() method?

PythonServer Side ProgrammingProgramming

NodeJs and Python are two main preferred languages among developers and web designers. But there are couple of areas where NodeJs fall short of python are numerical and scientic computation (AI, Machine learning, deep learning etc.). Whereas python provides lots of libraries to work with scientific computing lot easier.

Luckly, we can utilise the python libraries within our nodejs application by running python in the background and return back the result.

For this we are going to use the child_process standard library of NodeJs to spawn a pyton process in the background, do computation and return back the result to our node program.

Python script

We are going to write a simple python script which outputs messages to standard output along the way.

#Import library
import sys, getopt, time
def main(argv):
   argument = ''
   usage = 'usage: myscript.py -f <sometext>'
   # parse incoming arguments
   try:
      opts, args = getopt.getopt(argv,"hf:",["foo="])
   except getopt.GetoptError:
      print(usage)
      sys.exit(2)
   for opt, arg in opts:
      if opt == '-h':
         print(usage)
         sys.exit()
      elif opt in ("-f", "--foo"):
         argument = arg
   # print output
   print("Start : %s" % time.ctime())
   time.sleep( 2 )
   print('Foo is')
   time.sleep( 2 )
   print(argument)
   print("End : %s" % time.ctime())
if __name__ == "__main__":
main(sys.argv[1:])

Output

>python myscript.py -f "Hello, Python"
Start : Wed Feb 20 07:52:45 2019
Foo is
Hello, Python
End : Wed Feb 20 07:52:49 2019

Will generate same output as above, if we try to run with argument:

>python myscript.py --foo "Hello, Python"
>python myscript.py –h

Output

usage: myscript.py -f <Hello, Python>

NodeJs Interaction

Our nodejs script will interact with python script by first calling python script then pass script output to the client and render output in the client.

So let’s create a nodejs script, where we’ll try to create a child process using spawn() method.

server.js

const path = require('path')
const {spawn} = require('child_process')
/**
   * Run python myscript, pass in `-u` to not buffer console output
   * @return {ChildProcess}
*/
function runScript(){
   return spawn('python', [
      "-u",
      path.join(__dirname, 'myscript.py'),
     "--foo", "some value for foo",
   ]);
}
const subprocess = runScript()
// print output of script
subprocess.stdout.on('data', (data) => {
   console.log(`data:${data}`);
});
subprocess.stderr.on('data', (data) => {
   console.log(`error:${data}`);
});
subprocess.stderr.on('close', () => {
   console.log("Closed");
});

The above script will give output through .on(‘data’, callback). To prevent python from buffering output use the –f flag otherwise data event we’ll will not get print() statements from program until the end of execution.

>node server.js
data:Start : Wed Feb 20 10:56:11 2019
data:Foo is
data:some value for foo
data:End : Wed Feb 20 10:56:15 2019
Closed
raja
Published on 01-Apr-2019 16:01:18
Advertisements