Executing Python from NodeJS (hosted on an external domain) - python

So I have the following node.js express server running:
const express = require('express')
const app = express()
const PythonShell = require('python-shell');
app.get('/', (req, res) => {
res.send('Please append a search');
});
app.get('/:card', (req, res) => {
card = [req.params.card]
var pyshell = new PythonShell('search_card.py', {args: card});
pyshell.on('message', (message) => {
res.send(message);
});
pyshell.end((err) => {
if (err) throw err;
});
});
app.listen(9000, () => console.log('App listening on port 9000!'));
When I use the app using the local IP of the server (which is hosted within the intranet), everything works fine.
But if I use the external IP, the root of the app works ( / ) so clearly the connection is possible and the port is open, etc, but if I use the search function ( /search_query ), it takes a few seconds (as if the python script is actually running) and then chrome says ERR_CONNECTION_REFUSED (This site can't be reached).
Can anyone explain this behavior?
EDIT:
I put a console.log inside the pyshell.on('message') and the data is being received from the python program. Its as soon as it writes ends that it fails

Related

How to fetch data analyzed in python to node.js and pass it to angular?

I am new to angular and i want to display JSON data from python to angular with the help of node.js and I used child process to connect python and node.js but I dont know how to pass it to angular service
node.js file
const express = require('express')
const { spawn } = require('child_process')
const app = express()
const port = 8000
app.get('/', (req, res) => {
let dataToSend
let largeDataSet = []
// spawn new child process to call the python script
const python = spawn('python', ['test.py'])
// collect data from script
python.stdout.on('data', function (data) {
console.log('Pipe data from python script ...')
//dataToSend = data;
largeDataSet.push(data)
})
// in close event we are sure that stream is 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(largeDataSet.join(''))
})
})
app.listen(port, () => {
console.log(`App listening on port ${port}!`)
})
Technically you just have to send a Http GET request from your service.
I suggest that you should read and follow this offical http client guide to set it up correctly.
Here is a simple service snippet. This should be enough.
#Injectable({
providedIn: 'root',
})
export class MyService {
constructor(private http: HttpClient) {}
getData(): Observable<any> {
const url = '';
return this.http.get(url);
}
}

502 proxy error after 5 minutes of python script execution from express

The python script must take almost 2 hrs to compute. But I am getting 502 proxy error after 5mins in chrome and firefox. This happens even after changing the firefox default response timeout. I have also changed the express timeout to 0(infinity).
app.get("/claims", function (req, res) {
res.setHeader("Access-Control-Allow-Origin", "*");
const { spawn } = require("child_process");
const pyProg = spawn("python",["claims.py"]);
pyProg.stdout.on("data", function (data) {
return res.send(JSON.parse(JSON.stringify(data.toString())));
});
});
var server = app.listen(8000, function () {
console.log("App running on port 8000");
});
server.timeout = 0;

How to process requests in Python through an Express server

My approach has been to write a Flask server in Python and forward the request to that.
Demo.py
from flask import Flask
app= Flask(__name__)
#app.route("/")
def index():
return "Hello World"
if __name__ == '__main__':
app.run(debug=True)
Alternately, I also tried directly invoking a python script and then collecting the result from stdout.
Trial.js
const express = require('express')
const app = express()
app.get('/', (req, res) => {
const { spawn } = require('child_process');
const pyProg = spawn('python', ['C:/Users/Selectigence/PycharmProjects/jobapplicationbot/Sample3.py']);
pyProg.stdout.on('data', function(data) {
console.log(data.toString());
res.write(data);
res.end('end');
});
})
app.listen(4000, () => console.log('Application listening on port 4000!'))
I had a similar problem recently. I was running a Node JS server but the client request had to be processed in Python. So I went for an architecture which went like this:
The Web process was the Node JS server and the Background service was written in Python.
To implement this architecture, I had to answer the following questions:
How to implement the Background service.
How to get the Background service to communicate with the Web process.
I used celery to implement my Background service. For example:
tasks.py
import os
from celery import Celery
REDIS_URL='redis://127.0.0.1:6379'
app = Celery('tasks', backend=REDIS_URL, broker='REDIS_URL')
#app.task
def doSomething(arguments):
# Do whatever you want with the arguments
# and return the result ...
return result
My Web process was defined as follows:
app.js
const celery = require("node-celery");
const express = require("express");
const app = express();
const REDIS_URL = "redis://127.0.0.1:6379";
app.get("/", (req, res, next) => {
const client = celery.createClient({
CELERY_BROKER_URL: REDIS_URL,
CELERY_RESULT_BACKEND: REDIS_URL
});
client.on("error", function(err) {
console.log(err);
});
client.on("connect", function() {
const { arguments } = req.body;
// Here send task to Python process and
// process the result.
client.call("tasks.doSomething", [arguments], result => {
// The result object contains the result
// of the doSomething function in the "result"
// field along with other information regarding
// whether the call was successful.
res.send({ result: result.result });
client.end();
});
});
});
app.listen(4000, () => console.log('Application listening on port 4000!'))
Now I needed a communication channel between these two processes. I used redis as the message broker.
In the command line, I ran:
$ redis-server &
$ npm start &
$ celery -A tasks worker --loglevel=INFO &
Now, whenever I send a GET request at the server through the browser, the server forwards the arguments in the request to the Python service. This service processes the arguments, and returns the result to the server. The server finally fulfills the request with the response which is sent back to the browser.

Is there a way to increase the time out on a callback function in nodejs?

I am running a simple nodejs web application that executes a Python 2.7 script using the module python-shell. However, since this script takes too long to execute, around 3 minutes, the function fails with an ERR_EMPTY_RESPONSE error.
The function executes at the end, since Python still runs it in the background but the web application crashes.
generatePPage: (req, res) => {
const ps = require('python-shell');
let nombre = req.params.id;
var PythonShell = require('python-shell');
var options = {
pythonPath: '/usr/bin/python2.7',
args: [nombre],
};
var users = ps.PythonShell.run('./generateDetail.py', options, function (err, results) {
if (err){throw err;}
console.log('The results: %j', results);
res.render('success.ejs', {
title: 'Edit Project'
,project: ''
,message: 'Success'
});
});
},
How could I force it to wait longer?
Yes, you have to use setTimeout.
Check this link for more information: http://www.java2s.com/Tutorials/Javascript/Node.js_Tutorial/0270__Node.js_setTimeout_setInterval.htm
And also, check out this link: https://nodejs.org/ar/docs/guides/timers-in-node/
Solved it. The way to do it is to assign the return value of calling the listen function to a const and then assign a new timeout value in milliseconds.
const server = app.listen(port, () => {
console.log(`Server running on port: ${port}`);
});
server.timeout = 300000;

close a PythonShell on js (electron + flask)

I've googled around but I cannot find a proper answer, I have to say I'm pretty novice re NodeJS and electron: My problem is that I have connected my electron app with flask using Python-Shell but when I close my app, flask is still running in background even if close the terminal.
this is how I connect my app to flask:
var pyshell = require('python-shell');
pyshell.PythonShell.run('engine.py', function (err, results) {
if (err) console.log(err);
});
is there any way to "un-run" (close, quit, kill) the pyshell?
I've tried this but is not working:
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
pyshell.kill('engine.py'); // <-- I'm guessing here
app.quit()
}
This is the full code, is quite short, maybe could be useful to identify problems:
const {app, BrowserWindow} = require('electron')
function createWindow () {
window = new BrowserWindow({width: 800, height: 600})
window.loadFile('index.html')
var pyshell = require('python-shell');
pyshell.PythonShell.run('engine.py', function (err, results) {
if (err) console.log(err);
});
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
pyshell.kill('engine.py'); // <-- I'm guessing here
app.quit()
}
})
Using pyshell.kill() didn't actually kill the process rather it signals child process to stop. However, the child fails to stop sometimes.
Try using tree-kill npm package to kill that process, it handles such scenarios nicely.
// Declaring tree-kill
var kill = require('tree-kill');
//Killing python process
kill(pyshell.pid);

Categories

Resources