0

I created program python-shell.js located in Controllers directory. This program gives some data.

python-shell.js : CODE:

 var myPythonScriptPath = 'script.py';

// Use python shell
    const {PythonShell} = require("python-shell");
    var pyshell = new PythonShell(myPythonScriptPath);

    module = pyshell.on('message', function (message) {
    // received a message sent from the Python script (a simple "print" statement)
        console.log(message);
    });

    // end the input stream and allow the process to exit
    pyshell.end(function (err) {
    if (err){
        throw err;
    };

    console.log('finished');
    });

I created another server.js file outside of the controllers directory. It is to run the python-shell.js file.

server.js : CODE

var app = express();
var path = require('path');

app.use(express.static(path.join(__dirname, 'Controllers')));

app.get('/', function(req,res){
    res.sendFile(__dirname + '/Controllers');
});
app.listen(3000,function() {
console.log('Listening');
})

But this server.js code gives me the code that I wrote in the "python-shell.js" file. But I want server.js to give the data that "python-shell.js" gives when run independently instead of giving the code.

Ajax
  • 99
  • 5
  • 13

1 Answers1

0

As I understood. You would like to get data from a Python module when there is a request coming to your server, instead of just serving plain text source files.

As you can see the line res.sendFile(__dirname + '/Controllers'); would send file itself, it would not execute it and provide whatever your file sent to the console.

To achieve what I stated earlier you would need to import your JS file (in commonjs this is called requiring the module), and then call functions to get your data from there (if you want to separate server logic with python shell logic).

Inside python-shell.js you would need to get hold of res object provided as a part of app.get('/', function(req, res) {}) callback. So I would restructure code in following way:

python-shell.js

// Note that script.py refers to /script.py, not /Controllers/script.py
// As code bellow won't be called from within python-shell.js. More on that later
const myPythonScriptPath = 'script.py';

// Use python shell
const { PythonShell } = require("python-shell");

// From this file (module) we are exporting function 
// that takes req and res parameters provided by app.get callback
// Note that this file is not executed by itself, it only exposes
// a single function to whom is gonna import it
module.exports = function (req, res) {
    const pyshell = new PythonShell(myPythonScriptPath);

    // Create buffer to hold all the data produced 
    // by the python module in it's lifecycle
    let buffer = "";

    module = pyshell.on('message', function (message) {
        // received a message sent from the Python script (a simple "print" statement)
        // On every message event add that chunk to buffer
        // We add \n to the end of every message to make it appear from the new line (as in python shell)
        buffer += message + '\n';
    });

    // end the input stream and allow the process to exit
    pyshell.end(function (err) {
        if (err) {
            // If error encoutered just send it to whom requested it
            // instead of crashing whole application
            res.statusCode = 500;
            res.end(err.message);
        }
        // res.end sends python module outputs as a response to a HTTP request
        res.end(buffer);
        console.log('finished');
    });
}

And inside of server.js:

const express = require("express")
const path = require('path');

// We are importing our function from Controllers/python-shell.js file 
// and storing it as variable called pythonShellHandler
const pythonShellHandler = require("./Controllers/python-shell")

const app = express();

// express.static will serve source files from the directory
app.use(express.static(path.join(__dirname, 'Controllers')));

// Here we are passing our imported function as a callback
// to when we are recieving HTTP request to the root (http://localhost:3000/)
app.get('/', pythonShellHandler);
app.listen(3000, function () {
    console.log('Listening');
})

As you can see. I restructured your code so that python-shell.js exports to the other .js files a single function that takes Express's req and res parameters. And from within server.js I import this function.

This Node.js module system can be a bit hard to get gist of at first. If you are still confused, I recommend reading about node modules

Note: if your python script takes way too long to finish, or doesn't finish at all. Browser will just timeout your request.

Link0
  • 655
  • 5
  • 17
  • So when I'm trying to run python_shell.py it doesnot give me any output but when I was trying with previous code it was giving me the output. And in server.js part when I try to run it gives me :: (null): can't open file 'script.py': [Errno 2] No such file or directory. Can you please tell me how to fix it? It would be really helpful. – Ajax Jan 13 '20 at 13:55
  • Yes, with those changes python-shell.js does not execute function. It now only exposes it to the other js files. And about the error. As I said in the comments to the code variable `myPythonScriptPath` now refers not to the /Controlles/script.py, but to /script.py. Because we are not executing python-shell.js, the starting location of our node process is server.js, which is located outside of the Controllers folder. – Link0 Jan 13 '20 at 15:27
  • @Ajax, I imagine that your script.py file is located inside Controllers folder. Try moving it outside, or change the value of `myPythonScriptPath` to the `"Controllers/script.py"`. – Link0 Jan 13 '20 at 16:16
  • I gave path to myPythonScriptPath to /controllers/script.py so it shows the output.....as I tried const myPythonScriptPath = './controllers/script.py' but still gives me the same error: can't open file 'wikipedia.py': [Errno 2] No such file or directory – Ajax Jan 13 '20 at 16:28
  • If you want to access python-shell.js from server.js in the form you presented, I'm afraid that cannot be done. You need to restructure your code to make use of node's module system (which I've done). Doing so loses the ability of the file to execute any meaningful code if being executed with node, unless you use [this trick](https://stackoverflow.com/questions/4981891/node-js-equivalent-of-pythons-if-name-main). And about file not found error. The only thing I can note is maybe check that you've typed the path correctly and the file is present at the path specified – Link0 Jan 13 '20 at 16:30
  • It did work...with the path name...I was giving the wrong path. Thank you so much for your help. Also do you work with spacy. I would like to ask on that as well – Ajax Jan 14 '20 at 01:06