Hello I'm trying to interact with a python script inside a nodejs application at runtime.
The python script is more a command center for doing whatsapp operations called yowsup.
https://github.com/tgalal/yowsup/tree/master
I'm able to run the 'Yowsup Cli client' in a shell and work with it. But I want to run it in a nodejs application because it is written in python and I'm not good in python.
So what I did was to spawn the command I normally use in the shell like this:
var spawn = require('child_process').spawn,
ls = spawn('./yowsup/yowsup-cli', ['demos','--login', '49XXXXXXXXXXX:8bF0hUewVcX1hf6adpuasonFdEP=', '--yowsup', '-E', 's40']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code.toString());
});
The problem is, that I don't get any data from the process. The python script normally prints some output as start but I can't get anything inside node while the process is running.
I looked inside the python script and saw that the output is generated like this:
print("%s send '%s'" % (messageProtocolEntity.getFrom(False), messageProtocolEntity.getBody()))
How can I get some data from the python script on runtime?
This is slightly different than your approach and uses an npm lib, but does work (results is the stdout of the random_geo.py script):
var py = require('python-shell');
var pyOptions = {
mode: 'text',
pythonPath: '/opt/local/bin/python',
scriptPath: '.'
};
function getCoords(req, res, next) {
py.run('random_geo.py', pyOptions, function(err, results) {
if (err) {
console.log(err);
} else {
console.log(results);
}
});
}
Related
I'm new to using child process module in nodejs, and got stuck while using python's virtualenv libs
I have a post route in an expressjs api, which is intended to activate a python virtualenv, run python on exec() child process and deactivate the virtualenv.
I have it setup like this in one of the modules in the project folder
// importing node modules
const { exec } = require("child_process");
const kill = require("tree-kill");
Within the controller function, I'm trying to create child processes this way
let activate_proc = exec("source pyenv/bin/activate");
let command_proc = exec("python insert.py arg1 arg2", (error, stdout, stderr) => {
// handle status/messages with http codes
});
let deactivate_proc = exec("deactivate");
I was able to capture the pids for these processes and tried to kill using the tree-kill by pausing for 10 seconds
setTimeout(() => {
kill(command_proc.pid);
kill(activate_proc.pid);
kill(deactivate_proc.pid);
console.log("Killed all processes");
}, 10000)
This seems to be working but somehow, if the command_proc takes more time, it might conflict.
Is there a more efficient way to kill them asynchronously?
you can run them synchronously instead, with execSync
try this:
// importing node modules
const {execSync } = require('child_process');
let activate_proc = execSync('source pyenv/bin/activate');
let command_proc;
let deactivate_proc;
// use try/catch for stderr
try {
command_proc = execSync('python insert.py arg1 arg2');
// stdout buffer, turn it to string
const result = command_proc.toString();
console.log('command_proc result: ', result);
// handle status/messages with http codes
// ... process command_proc
// finish
deactivate_proc = execSync('deactivate');
} catch (err) {
// handle command_proc err
console.log('output', err);
console.log('sdterr', err.stderr.toString());
}
Error, could not create TXT output file: No such file or directory
tesseract ./downloads/en.jpg outputs/1585336201.287781output -l eng
is the error i'm having trouble with, this command works fine from the python script but not through a childprocess spawn, downloads and the .py script are in the same folder, and both of them are in a folder next to the nodejs script
this is the method that i call from a post function to give it the imagine fine that i need to transcribe, then the python script can't run the tesseract command, even though it can do it when its run manually
const verif = async (fileName, filePath) => {
var uint8arrayToString = function(data){
return String.fromCharCode.apply(null, data);
};
const spawn = require('child_process').spawn;
const scriptExecution = spawn('python',['-u', './diploma/app.py']);
var data = JSON.stringify([fileName]);
scriptExecution.stdin.write(data);
scriptExecution.stdin.end();
scriptExecution.stdout.on('data', (data) => {
console.log(uint8arrayToString(data));
});
scriptExecution.stderr.on('data', (data) => {
// As said before, convert the Uint8Array to a readable string.
console.log(uint8arrayToString(data));
});
scriptExecution.on('exit', (code) => {
console.log("Process quit with code : " + code);
});
return true;
}
The problem was that tesseract needed windows permissions when executed from the js file
Complete new to Node.js. Recently I was provided with a task to web scrape a website with python and connect the python script to Node.js using python-shell package in Node.js. I'm done with the scraping part but not having any prior knowledge of Node.js. Can you please guide me on how to approach this problem?
import sys
# Takes first name and last name via command
# line arguments and then display them
print("Output from Python")
print("First name: " + sys.argv[1])
print("Last name: " + sys.argv[2])
# save the script as hello.py
// import express JS module into app
// and creates its variable.
var express = require('express');
var app = express();
// Creates a server which runs on port 3000 and
// can be accessed through localhost:3000
app.listen(3000, function() {
console.log('server running on port 3000');
} )
// Function callName() is executed whenever
// url is of the form localhost:3000/name
app.get('/name', callName);
function callName(req, res) {
// Use child_process.spawn method from
// child_process module and assign it
// to variable spawn
var spawn = require("child_process").spawn;
// Parameters passed in spawn -
// 1. type_of_script
// 2. list containing Path of the script
// and arguments for the script
// E.g : http://localhost:3000/name?firstname=Mike&lastname=Will
// so, first name = Mike and last name = Will
var process = spawn('python',["./hello.py",
req.query.firstname,
req.query.lastname] );
// Takes stdout data from script which executed
// with arguments and send this data to res object
process.stdout.on('data', function(data) {
res.send(data.toString());
} )
}
// save code as start.js
After saving the Python script and server script code, run the code from its source folder by following command :
node start.js
Access the application through link :
localhost:3000/name?firstname="Enter first name"&lastname="Enter last name"
For e g. : localhost:3000/name?firstname=Ram&lastname=Sharma
Since you must use python-shell package and assuming that your source file is my_file.py, you can simply read the documentation of the npm package and in particular this example:
import {PythonShell} from 'python-shell';
let pyshell = new PythonShell('my_script.py'); // 1
pyshell.on('message', function (message) {
// received a message sent from the Python script (a simple "print" statement)
console.log(message); // here there will be logged your pyoutput
}); // 2
// end the input stream and allow the process to exit
pyshell.end(function (err,code,signal) {
if (err) throw err;
console.log('The exit code was: ' + code);
console.log('The exit signal was: ' + signal);
console.log('finished');
console.log('finished');
}); // 3
What this script does:
launches the python script without arguments
gets every write on the stdoutput of your pyscript and logs it into nodejs stdout.
closes the python script reporting some optional info
If your scripts logs the webscrape into the stdout this should work fine.
I absolutely love using Node.JS for my web projects but i also love using Python at the same time, so i have been wondering, if is it possible to run Python scripts from Node, for example my Node.JS backend calls a python script to retrive some data from a SQL Database and gives it back to Node (i know i can do that all in Node but just using an example). I thought about doing it this way
1.Node creates a Json files which contains the variable the Python script will use(for example name:Jon birthDate:1996)
2.It runs a python script that reads those variables from that Json file(so it searches for Jon born in 1996)
3.It deletes the Json file when its done
4.Rinse and Repeat
Would this be a good and safe way of doing this type of thing or are there any other ways of running and "modifiying" the Python script?
I had to build a node app, but for the backend calculations, it seemed better to use NumPy and Pandas, so I did what you are doing... in the end I found an npm package called python-shell.
It works via promises, so I'd call my calculation script, and also would do some clean up with another Python script if there were any errors.
Worked pretty good. Code was something like this:
const PythonShell = require('python-shell');
router.get('/calc', (req, res) => {
PythonShell.run('py/calculate.py', {pyPath: pyPath , args: [tmpPath],}, function(err, results) {
if (err) {
PythonShell.run('py/clean_up.py', {pyPath: pyPath, args: [tmpPath2]}, function(err, results2) {
if (err) throw err;
res.json(
{
message: "error: Running clean up",
ang: 0,
vec: 0,
}
);
});
} else {
let data = JSON.parse(results);
let message = data[0];
let ang = data[1];
let vec = data[2];
res.json(
{
message: message,
ang: ang,
vec: vec,
}
);
}
});
});
I'm using python-shell to run a python script that classifies an image and returns a yes/no if that image is what I'm looking for or not.
Node.js code:
app.get('/classify', function(req, res) {
var options = {
mode: 'text',
pythonOptions: ['-u'],
scriptPath: 'src/',
args: ['--image', '../../images/image.png', 'classifer.xml']
};
PythonShell.run('classify_images.py', options, function(err, results) {
if (err) throw err;
// results is an array consisting of messages collected during execution
console.log('results: %j', results);
});
res.send('classify');
});
If I run the command as a python script, it works fine but when I run it through node.js, it gives me back all no's.
The python command (in src) is:
python classify_images.py --image ../../images/image.png classifer.xml
Apparently I didn't put in the right file path - it worked after that.