how to run a python script from node js

Question:

I have written a server in node.js on Raspberry Pi.
I want to run a python script from it but it does not execute the line. On previous instances, I have run files but coming to this instance of socket.io I can’t run the file! Though the console shows accurate output passed to it from the client but it fails to read the file. The socket is responsible for movement.

/*jshint esversion: 6 */
var express = require('express');
// library for executing system calls
const spawn = require('child_process').spawn;
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
app = express();
server = require('http').createServer(app);
io = require('socket.io').listen(server);
var colour = require('colors');
var ip = require('ip');

var PortNumber = 3000;

var xPos = 0, yPos = 0;

server.listen(PortNumber);
app.use(express.static('public'));


io.sockets.on('connection', function (socket) {

    socket.emit('ip', {value: 'http://' + ip.address() + ':8081'});

    // otp generation socket
    socket.on('userEmail', function (data) {
        var userEmail = data.value;

        // system call to generate OTP
        const OTPgeneration = spawn('python', [__dirname + '/python/OTPgeneration.py', userEmail]);
        OTPgeneration.stdout.on('data', (data) => {
            console.log(`${data}`);
        });
    });

    // otp submit button socket
    socket.on('userOtp', function (data) {
        var userOtp = data.value;
        console.log(userOtp);

        // system call to generate OTP
        const otpValidate = spawn('python', [__dirname + '/python/OTPvalidation.py', userOtp]);
        otpValidate.stdout.on('data', (data) => {
            console.log(`${data}`);

            // Get last output from python file
            var lastChar = `${data}`.slice(-2);

            if (lastChar === '0n') {
                console.log('Wrong OTP');
            }
            else io.sockets.emit('otpConformation', {value: 'confirm'}); //sends the confirmation to all connected clients
        });
    });

    // x y values socket
    socket.on('servoPosition', function (data) {
        servoPosition = data.value;
        // servoPosition[0] is x and servoPosition[1] is y
        console.log('Reveived X: ' + servoPosition[0] + '  Y: ' + servoPosition[1]);
        // system call for i2c comminication
        const i2cData = spawn('python', [__dirname + '/python/sendI2C.py', servoPosition[0], servoPosition[1]]);
        i2cData.stdout.on('data', (data) => {
            console.log(`${data}`);
        });
    });

    // movement socket
    socket.on('movement', function (data) {
        var m = data.value;
            console.log("Movement :" + m);
  const submitMove = spawn('python', [__dirname + '/python/move.py', m]);
        submitMove.stdout.on('data', (data) => {
            console.log(`${data}`);
        });

    });
});

console.log('Server Running @'.green + ip.address().green + ":3000".green);

function readTextFile(file) {
    var rawFile = new XMLHttpRequest();
    //var rawFile = new XMLHttpRequest();
    rawFile.open("GET", file, false);
    rawFile.onreadystatechange = function () {
        if(rawFile.readyState === 4) {
            if(rawFile.status === 200 || rawFile.status === 0) {
                allText = rawFile.responseText;
                //alert(allText);
            }
        }
    };
    rawFile.send(null);
}
Asked By: pradumna

||

Answers:

While using Node’s native “child_process” module is the most performant option, it can be tedious in getting it to work. A quick solution is to use the node-cmd module.
Run npm i node-cmd --save to install it.
Import it via var cmd = require('node-cmd'); at the top of your server file. Then,

var pyProcess = cmd.get('python YOURPYTHONSCRIPT.py',
              function(data, err, stderr) {
                if (!err) {
                  console.log("data from python script " + data)
                } else {
                  console.log("python script cmd error: " + err)
                  }
                }
              );

Editing as needed. node-cmd has 2 methods which invoke it, get and run. run simply runs the provided CLI command whereas get provides the use of a callback allowing for better error handling and makes working between stdin, stdout, stderr much easier.

Answered By: DaneTheory

Consider using a package instead of dealing with spawning processes by your self.
you can check this package on npm that i created- native-python

it provides a very simple and powerful way to run python functions from node
might solve your problem.

import { runFunction } from '@guydev/native-python'

const example = async () => {
   const input = [1,[1,2,3],{'foo':'bar'}]
   const { error, data } = await runFunction('/path/to/file.py','hello_world', '/path/to/python', input)

   // error will be null if no error occured.
   if (error) {
       console.log('Error: ', error)
   }

   else {
       console.log('Success: ', data)
       // prints data or null if function has no return value
   }
}

python module

# module: file.py

def hello_world(a,b,c):
    print( type(a), a) 
    # <class 'int'>, 1

    print(type(b),b)
    # <class 'list'>, [1,2,3]

    print(type(c),c)
    # <class 'dict'>, {'foo':'bar'}
Answered By: Guy-dev
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.