How to send next() in a callback function - python

Here i want to send the next() when my data is received from the python script but i am getting Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.
const {PythonShell} = require('python-shell');
module.exports = (req, res, next)=>{
let myPythonScriptPath = 'encrypt.py';
const pyshell = new PythonShell(myPythonScriptPath);
let path = req.file.path;
pyshell.send(path);
pyshell.on("message", function(data){
console.log(data);
req.filepath = data;
next();
})
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err){
throw err;
}
});
}
but it is working when i put next() at the end of code but then my req.filepath is undefined
const {PythonShell} = require('python-shell');
module.exports = (req, res, next)=>{
let myPythonScriptPath = 'encrypt.py';
const pyshell = new PythonShell(myPythonScriptPath);
let path = req.file.path;
pyshell.send(path);
pyshell.on("message", function(data){
console.log(data);
req.filepath = data;
})
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err){
throw err;
}
});
next();
}
What i want is to store the data coming from python script in req.filepath which is to be sent to next middleware. Can anyone help me with this?

You're seeing this behavior due to the order of asynchronous tasks, which I've enumerated below in the comments. The execution doesn't necessarily happen in the same sequence that the code is written, so, you're either trying to modify a request/response after the PyShell command has already been sent (case #1 above), or Express has already moved on to the next middleware before req.filepath has been set (case #2 above).
const {PythonShell} = require('python-shell');
module.exports = (req, res, next) => {
let myPythonScriptPath = 'encrypt.py';
const pyshell = new PythonShell(myPythonScriptPath);
let path = req.file.path;
pyshell.send(path); // 1) Send the command
// 3) This anonymous function is invoked, but it's
// too late -- the command has already been sent
// and has continued on to the next middleware.
pyshell.on("message", function(data){
console.log(data);
// This will be undefined in the next middleware
// because it moved on before it was actually set.
req.filepath = data;
})
// 4) This anonymous function gets run last.
pyshell.end(function (err) {
if (err){
throw err;
}
});
next() // 2) Tell Express to continue on to the next middleware.
}
Do you have other middleware before or after this one that is trying to modify or send an HTTP response?

Using callback methodolgy this can be acheived by sending the result of the function in callback().(Here callback is next)
The code is given below:
const {PythonShell} = require('python-shell');
module.exports = function (req, res, next){
try{
let myPythonScriptPath = '/home/anmolmiddha/Projects/coreshare/server/api/python/encrypt.py';
const pyshell = new PythonShell(myPythonScriptPath);
let path = req.file.path;
pyshell.send(path);
pyshell.on("message", function(data){
});
pyshell.end(function (err, rslt) {
if(err){
res.status(500).json(err);
}
else{
req.filepath = JSON.stringify(path).split('"')[1];
next(rslt);
}
});
}
catch(error) {
return res.status(401).json({
message: "Invalid token Auth failed"
})
}
}

Related

How can I use node.js to run a python file that runs forever?

I am wondering how to use node.js to run a python file that prints until it stops.
Right now when I run it it does not print anything, is there a way I can make it work properly?
Node.js
let {PythonShell} = require('python-shell')
var options = {
pythonOptions: ['-u']
};
PythonShell.run('main.py', options, function (err, result){
if (err) throw err;
// result is an array consisting of messages collected
//during execution of script.
if (result !== null){
console.log(result.toString());
}
});
PythonShell.run('main.py', options, function (err, result){
if (err) throw err;
// result is an array consisting of messages collected
//during execution of script.
if (result !== null){
console.log(result.toString());
}
});
A function similar to mine
main.py
num = 1
while True:
print(num)
num += 1
I'm not familiar with python-shell package but you can easily spawn a new process to run python programs by using spawn method from child_process package that comes with node.
Here is how you can use it:
const { spawn } = require("child_process");
const cmd = spawn("python3", [__dirname + "/main.py"]);
cmd.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});
cmd.stderr.on("data", (data) => {
console.error(`stderr: ${data}`);
});
cmd.on("close", (code) => {
console.log(`child process exited with code ${code}`);
});
Read the documentation for more info [link]

is there any method how to call python file from node.js

this is my first time using stackoverflow asking questions
so my problem is i don't know how can i call these python files to execute from index.js file
technically i want to call python files after i press submit button
our web page output
and this is my code structure in index.js
const express = require("express")
const path = require("path")
const multer = require("multer")
const app = express()
//Call python script
const { spawn } = require('child_process');
const testing = spawn('python', ['test.py']);
testing.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
filename: function (req, file, cb) {
console.log(file.mimetype);
if(file.mimetype == "video/mp4"){
cb(null, file.fieldname + "-" + Date.now()+".mp4")
}
else cb(null, file.fieldname + "-" + Date.now()+".jpg")
}
})
app.post("/uploadFile",function (req, res, next) {
// Error MiddleWare for multer file upload, so if any
// error occurs, the image would not be uploaded!
upload(req,res,function(err) {
if(err) {
// ERROR occured (here it can be occured due
// to uploading image of size greater than
// 1MB or uploading different file type)
res.send(err)
}
else {
// SUCCESS, image successfully uploaded
res.send("Success, your file has been uploaded!")
}
})
})
// Take any port number of your choice which
// is not taken by any other process
app.listen(8080,function(error) {
if(error) throw error
console.log("Server created Successfully on PORT 8080")
})

Running a Python script from Node.js returns blank

I'm following the posts here but when I go to localhost:3000, the page is blank. I've tried to change my Python script path but that does not seem to work. It seems that it's not accessing the script1.py file. I'm not sure why.
NOTE: script1.py and index.js are both in the same directory.
Here is my index.js:
const express = require('express');
const {spawn} = require('child_process');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
var dataToSend;
const python = spawn('python', ['script1.py']);
python.stdout.on('data', function (data) {
dataToSend = data.toString();
});
python.on('close', (code) => {
console.log(`child process close all stdio with code ${code}`);
res.send(dataToSend)
});
});
app.listen(port);
Here is my script1.py:
print('Hello from python')
And http://localhost:3000/ is completely blank (though it is being run) but it's not displaying 'Hello from python'.
this is how it worked for me:
app.js file:
const spawn = require("child_process").spawn;
const pythonProcess = spawn('python', ["./p1.py"]);
const http = require('http');
let pythonData = null;
pythonProcess.stdout.on('data', (data) => {
pythonData = data.toString();
});
let app = http.createServer((req, res) => {
// Set a response type of plain text for the response
if(req.url === "/getPyt") {
res.end(JSON.stringify(pythonData));
}
if(req.url === "/") {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end("Hello there");
}
});
// Start the server on port 3000
app.listen(3000, 'localhost');
console.log('Node server running on port 3000');
p1.py :
import sys
print("Hello there")
sys.stdout.flush()
I think what you missed is that ./ refferencing python file.
I've commented sys.stdout.flush() inside p1.py and it's also working.

Call a Python script from React with next routing and a node.js server

I am working on an ethereum application that uses react, next-routing and a basic node.js server. I want to run a python script on a specific route, claimAnalysis to be specific, in order to perform some predictions. I want the script to be executed every time I visit the claimAnalysis route.
server.js
const express = require("express")();
const next = require("next");
const app = next({
dev: process.env.NODE_ENV !== "production"
});
const routes = require("./routes");
const handler = routes.getRequestHandler(app);
app.prepare().then(() => {
const server = express.use(handler);
server.listen(3000, (err) => {
if(err) throw err;
console.log("Server ready on localhost:3000");
});
});
routes.js
const routes = require("next-routes")();
routes
.add("/insurance/new", "/insurance/new")
.add("/insurance/:address", "/insurance/show")
.add("/insurance/:address/claims", "/insurance/claims/index")
.add("/insurance/:address/claims/new", "/insurance/claims/new")
.add("/insurance/:address/claims/:id/claimAnalysis", "/insurance/claims/claimAnalysis");
module.exports = routes;
Please guide me if I can call a function from the claimAnalysis.js file that runs the python script.
If you're using Node 10+, you can use util.promisify to execute your python scriptwhich returns a Promise<{ stdout, stderr }> object. See an example below:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
// function to execute python script
async function executeScript(path) {
try {
const { stdout, stderr } = await exec(`python3 ${path}`);
console.log('stdout:', stdout);
console.log('stderr:', stderr);
} catch (e) {
console.error(e);
}
}
Now let's use the function in your route:
app.get('/insurance/claims/claimAnalysis', async function (req, res) {
await executeScript();
res.send('claimAnalysis request completed');
...
})
You can use "child_process" to finish function.
You can see this example:
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");
});

NodeJs: Get output of python-shell to send back to client

I am trying to create a website where a user can submit python code, it gets sent to my server to be executed and I send back the results to the client. Currently I am using a NodeJs server and need to run the python code from there. To do this, I am using Python-shell like so:
const runPy = async (code) => {
const options = {
mode: 'text',
pythonOptions: ['-u'],
scriptPath: path.join(__dirname, '../'),
args: [code],
};
const result = await PythonShell.run('script.py', options, (err, results) => {
if (err) throw err;
return results; <----- HOW DO I RETURN THIS
});
console.log(result.stdout);
return result;
};
I understand I can console.log() the results in the PythonShell.run() but is there a way to return the results from my runPy function to then be manipulated and sent back to the client?
It looks from the python-shell documentation that the PythonShell.run method doesn't have an async mode. So, one option is to wrap it in a promise:
const runPy = async (code) => {
const options = {
mode: 'text',
pythonOptions: ['-u'],
scriptPath: path.join(__dirname, '../'),
args: [code],
};
// wrap it in a promise, and `await` the result
const result = await new Promise((resolve, reject) => {
PythonShell.run('script.py', options, (err, results) => {
if (err) return reject(err);
return resolve(results);
});
});
console.log(result.stdout);
return result;
};

Categories

Resources