I am trying to execute this piece of node js code which execute a python script. Through this code works fine. but the response "running" and "finished" are displayed on front end immediately. "finshed" has to be displayed once the execution of python scripts gets completed.
app.post('/execute', function(request, response){
response.write("running");
console.log("executing")
var pyshell = new PythonShell('./python_codes/test.py')
pyshell.on('message', function (message) {console.log(message);});
pyshell.end(function (err) {if (err){throw err;};console.log('finished');});
response.write("finished");
response.end();
});
2 Answers 2
You should add your response inside the callback function
app.post('/execute', function(request, response){
response.setHeader('Connection', 'Transfer-Encoding');
response.setHeader('Content-Type', 'text/html; charset=utf-8');
response.write("running");
console.log("executing")
var pyshell = new PythonShell('./python_codes/test.py')
pyshell.on('message', function (message) {console.log(message);});
pyshell.end(function (err) {
if (err){
throw err;
};
console.log('finished');
response.write("finished");
response.end();
});
});
2 Comments
response.setHeader('Connection', 'Transfer-Encoding'); response.setHeader('Content-Type', 'text/html; charset=utf-8'); To allow browser to show the content immediately.It happens because the PythonShell class is asynchronous. What your code is doing is creating a PythonShell object, storing it in variable pyshell, and then adding a few events to the pyshell object. It then directly continues to write "finished".
Because writing "finished" is not part of the callback for the end() function, it happens right away. I see at least three things you can do:
- If the HTTP library you are using supports it, just add the
response.write("finished"); response.end();code to thepyshell.endcallback. - Call Python using a library which supports pausing the current execution thread (or use execSync). This is bad practice, because it defeats the purpose of using a concurrent framework like node.js, but would work.
- Use WebSockets (or socket.io, which works even if WebSockets aren't available, such as through CloudFlare) to transmit the "finished" message.
PythonShelluseschild_process.spawn, which is asynchronous - you're saying here "Run this python thing, and tell me when it's done by using the callback I've given you with.end, and while you're doing that I will carry on with my own stuff". I suspect you'll need to either wait forpyshell.terminatedto show the right value, or pass the response into the.endcallbackapp.postcallback is done runningresponse.end()will be called implicitly.