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")
})
Related
What I want to do:
I would want to create 2 endpoints /servers and /items. Both endpoints should send json from GET request, but for /servers endpoint, I have python script that scrapes data from the website and outputs json file and here is a problem, because I can't run this python script as I don't have required imports and don't really know how to add them using node.js.
server.js
const app = require('express')();
const { dirname } = require('path');
const appDir = dirname(require.main.filename);
const fs = require('fs');
const { exec } = require('child_process');
const { PythonShell } = require('python-shell');
const PORT = 8080;
const options = {
pythonPath: process.env.PYTHONPATH
};
app.get('/servers', (req, res) => {
// Run the serversScrapper.py script and update the serversList.json file
PythonShell.run(`${appDir}/serverScrapper.py`, options, (err, results) => {
if (err) {
console.error(err);
res.sendStatus(500);
return;
}
// Send the updated serversList.json file as the response
res.sendFile(`${appDir}/serversList.json`, (err) => {
if (err) {
res.status(500).send(err);
}
});
});
});
app.get('/items', (req, res) => {
res.sendFile(`${appDir}/itemsList.json`, (err) => {
if (err) {
res.status(500).send(err);
}
});
});
// Run the script every 2 minutes
setInterval(() => {
PythonShell.run(`${appDir}/serverScrapper.py`, null, (err, results) => {
if (err) {
console.error(err);
}
});
}, 2 * 60 * 1000);
app.listen(PORT, () => console.log('Server up at 8000'))
I've copied and pasted only script file to the project folder, so that might be an issue, but I think there should be a way for node.js to automatically start python script and import required libraries (bs4, requests, json)
error log:
PythonShellError: ModuleNotFoundError: No module named 'bs4'
at PythonShell.parseError (/rbd/pnpm-volume/eb08c55a-3afc-4775-99f3-8543de0493fc/node_modules/python-shell/index.js:295:21)
at terminateIfNeeded (/rbd/pnpm-volume/eb08c55a-3afc-4775-99f3-8543de0493fc/node_modules/python-shell/index.js:190:32)
at ChildProcess.<anonymous> (/rbd/pnpm-volume/eb08c55a-3afc-4775-99f3-8543de0493fc/node_modules/python-shell/index.js:182:13)
at ChildProcess.emit (events.js:400:28)
at Process.ChildProcess._handle.onexit (internal/child_process.js:282:12)
----- Python Traceback -----
File "/app/serverScrapper.py", line 2, in <module>
from bs4 import BeautifulSoup {
traceback: 'Traceback (most recent call last):\n' +
' File "/app/serverScrapper.py", line 2, in <module>\n' +
' from bs4 import BeautifulSoup\n' +
"ModuleNotFoundError: No module named 'bs4'\n",
executable: 'python3',
options: null,
script: '/app/serverScrapper.py',
args: null,
exitCode: 1
}
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.
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");
});
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"
})
}
}
I want to run python script in server (Google Compute Engine). So I made a Cloud Function code using python-shell. However this error appeared.
Error: python: can't open file
'/home/dmproject0608/test2/FaceDetect_.py': [Errno 2] No such file or
directory
And this is my Cloud Function:
const functions = require('firebase-functions');
const mkdir=require('mkdirp-promise');
const gcs=require('#google-cloud/storage')();
const spawn=require('child-process-promise').spawn;
const path=require('path');
const os=require('os');
const fs=require('fs');
var pythonShell=require('python-shell');
exports.Test = functions.storage.object().onFinalize((object) => {
const filePath = object.name;
const fileName = path.basename(filePath, path.extname(filePath));
const fileDir = path.dirname(filePath);
const fileBucket=object.bucket;
const tempLocalFile = path.join(os.tmpdir(), filePath);
const tempLocalDir = path.dirname(tempLocalFile);
const bucket=gcs.bucket(fileBucket);
if (object.resourceState === 'not_exists') {
console.log('This is a deletion event.');
return;
}
return mkdir(tempLocalDir).then(()=>{
return bucket.file(filePath).download({destination : tempLocalFile});
}).then(()=>{
console.log('Download is complete %j',tempLocalFile);
var options={
mode:'text',
pythonPath:'',
pythonOptions: ['-u'],
scriptPath:'/home/dmproject0608/test2',
args:[ tempLocalFile]
};
pythonShell.run('FaceDetect_.py',options,function(err,results){
if(err) throw err;
console.log('result: %j',results);
});
});
});
May be a bit late for this response, try absolute paths when using Python-shell.