ZeroRPC between nodejs and Python running only for the first time - python

We are trying to call a python module from NodeJS using ZeroRPC.
Nodejs Code:
app.get('/topList', function(req, res){
var zerorpc = require("zerorpc");
var client = new zerorpc.Client({ timeout: 3000, heartbeatInterval: 300000 });
console.log('Here');
client.connect("tcp://127.0.0.1:4212");
console.log('And Here');
client.invoke("toplist", '2015-02-13T05:46:29.800Z', '2015-02-13T08:46:29.800Z', function(error, tlist, more)
{
console.log('And Here also');
if(error) {
console.error(error);
}
console.log(tlist);
res.send(tlist);
client.close();
});
});
Python code:
import zerorpc
import logging
import gevent
logging.basicConfig()
class HelloRPC(object):
def toplist(self, fromtime, tilltime):
print 'Python Hello'
# Doing some some manipulations and placing the result in the variable top_20
return top_20
p = HelloRPC()
s = zerorpc.Server(p)
s.bind("tcp://127.0.0.1:4212")
s.run()
First we ran the python code to up the server. Next we start the nodejs code.
Now in the browser for the first time if we try for localhost:8080/topList, nodejs issues an request to python, then python program is running and returning the result to nodejs, then in the browser we are able to see the result.
The problem comes if we try for the second time localhost:8080/topList, nodejs not able to invoke the python code. We didn't see 'Python Hello' in python console.
We are not able to fix this scenario. It is only running for the first time, then nodejs not able to invoke python. Is the server is getting closed after runnig first time.
We also tried to use While True or gevent like below. But still same issue.
While True:
p = HelloRPC()
s = zerorpc.Server(p)
s.bind("tcp://127.0.0.1:4212")
s.run()
#gevent.spawn(s.run)
Can anyone will provide some idea to fix this ?

Related

I want to call a python function from a nodes lambda function in AWS

I have used the spawn module to call a script1.py function from my nodejs export handler but it does not work.
The index.js file is as follows-:
exports.handler = async function(event, context) {
process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT']
//this was added as mentioned in the aws documentation
let dataToSend
const python = spawn('python', ['script1.py']);
python.stdout.on('data', function (data) {
console.log('Pipe data from python script ...');
dataToSend = data.toString();
});
console.log("EVENT: \n" + JSON.stringify(event, null, 2)+ dataToSend)
return dataToSend
}
and the python script1.py is as follows-:
print('hello from python')
I tested it using postman and it gave an internal server error.
I want to run a spacy module hence I need to integrate my python code with my nodejs code.
This will not work, because there is no Python installed in the NodeJS runtime.
As far as I can tell, you have three options:
Build a Docker image containing NodeJS and Python and use it with AWS Lambda.
Port the code from the Python Lambda into your NodeJS Lambda.
Create two Lambdas. One Python, one NodeJS and invoke one from the other (thanks manpreet from the comments)

Spawning (and killing) Uvicorn/FastAPI backend from Electron (or Node.js)

I'm building a Python backend for an Electron app using FastAPI (and Uvicorn). I develop on both macOS and Windows, so I'm looking for a cross-platform solution to the following question.
How can I spawn and gracefully kill a python Uvicorn server from Node.js (specifically the electron.js script of my Electron app)?
The only way I've been able to launch the server is with exec instead of spawn. So this works:
const { spawn, exec, execFile } = require("child_process");
function launchPython() {
pythonProcess = exec(
"C:\\Users\\user2\\miniconda3\\envs\\myenv\\python.exe .\\py_src\\main.py"
);
console.log("Python process started in dev mode")
return pythonProcess;
}
But this does not:
function launchPython() {
pythonProcess = spawn(
"C:\\Users\\user2\\miniconda3\\envs\\myenv\\python.exe .\\py_src\\main.py"
);
console.log("Python process started in dev mode")
return pythonProcess;
}
.\py_src\main.py looks like this:
import uvicorn
if __name__ == "__main__":
uvicorn.run(
"app.api:app",
host="0.0.0.0",
port=8000,
reload=True
)
Also, upon exiting the Electron app, the Uvicorn server is not killed. The "exit" code in my main electron.js file is as follows:
app.on("window-all-closed", function () {
if (process.platform !== "darwin") {
pythonProcess.kill();
app.quit();
return
}
});
So two main questions:
Why doesn't spawn work to run the python Uvicorn server (py_src\main.py)? NOTE: I'm using a specific python version from a Miniconda environment. Could that be the cause?
How can I shutdown the Uvicorn server programmatically when the Electron app exits (because killing the python process that I opened with exec doesn't seem to work)?
Eventually I'm going to use Pyinstaller to build an executable for the FastAPI backend, and launch it with child_process.execFile, which is why I need a programmatic way to shutdown the Uvicorn server (e.g. with a "quit" or "shutdown" call to the API)

Shutting down Flask application from C#?

I am relaying HTTP requests from a C# application by sending JSON data to a localhost flask application, sending the requests with python, and relaying the response back to my C# application. Needs to be done this way because the server I am dealing with is 3rd party and fingerprints SCHANNEL requests and sends back dummy data (Does this with Powershell as well, but not curl, Postman, or Python).
var process = new Process();
process.StartInfo = new ProcessStartInfo()
{
FileName = "cmd.exe",
Arguments = #" /k python Assets\Scripts\server.py",
UseShellExecute = true
};
process.Start();
I found this solution, which uses an endpoint (/shutdown)
def shutdown_server():
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
Get a warning that it is being deprecated. I can live with that, but my OCD makes me want to do this properly. The warning tells me this is a hacky solution.
I am new to python/flask. What would be a good way about going about this?
Sidenote: process.Kill() doesn't work. Wish it did.
process.CloseMainWindow() seems to do the trick from my initial tests. Why process.Close() or process.Kill() do not work, is beyond me.

How to setup SocketIO connection to NodeJS websocket from Python client?

I've got a simple nodejs server that runs socketio and I can do 2 way communication with the client from the HTML. Now I'm also trying to connect to the same nodejs websocket from a Python script, but not getting connected.
Simplified Node JS webserver:
var http = require('http').createServer(handler);
var fs = require('fs');
var io = require('socket.io')(http)
http.listen(8080);
function handler (req, res) {
fs.readFile(__dirname + '/public/index.html', function(err, data) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
return res.end();
});
}
io.sockets.on('connection', function (socket) {
setInterval(() => {
socket.emit('temp', 'tempfromserver')
}, 1000)
});
The Python script that wants to connect to the nodejs with websocket:
import socketio
sio = socketio.Client();
sio.connect('http://localhost:8080')
#sio.event
def message(data):
print('received message')
def connect():
print('socketio connected')
Is it possible to connect with a websocket via socketio to the nodejs server? If so, what am I doing wrong?
End goal is to collect sensor data from python script on raspberry pi and send to nodejs server which in its turn saves it to DB and sends through to HTMl client. Perhaps there is a better setup to do this.
I believe I asked a similar question and got an answer. My setup was a little different, and used a web-socket, but it will at least allow you to connect between Node JS and Python, and then maybe you can build from there, Using Socket IO and aiohttp for data transfer between node JS and Python. The setup was also originally based off a html script on the node JS side, so that may help as well in comparing it to your setup.

I need to host node js through python

var util = require('util');
var exec = require('child_process').spawn;
var run = exec('/usr/bin/python', ['-m', 'SimpleHTTPServer', '9002']);
run.stdout.on('data', function(data){
console.log('stdout: ' + data.toString());
});
run.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
test.py
from bottle import route, run, template
#route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)
run(host='localhost', port=9002)
I am new to node js and python just i want do communicate between node js to python with localhost. A simple python script with localhost url to hit node js url after running node js scrpit whih call python script in node and host the same on web browser.
Not entirely sure I see the problem. Your code works.
1) Make sure you access localhost:9002
2) If you meant to run your bottle code, then use
var run = exec('/usr/bin/python', ['/path/to/bottle_server.py']);
As for communicating back and forth between the Python code and the Node.js code, then you need sockets. Some libraries to look at could include socket.io or use a messaging queue like zmq.
If you want one-way communication to your python API, then you need to perform HTTP requests to http://localhost:9002 from the Node code. Alternatively, Node is very much capable of the same functionality you've included in the Python code on its own.
EDIT
Regarding below comments, here is an updated script. You need to inherit the parent's stdout and stderr, otherwise, as you see in the image above, it thinks python is printing to stderr
var util = require('util');
const spawn = require('child_process').spawn;
var run = spawn('/usr/bin/python', ['-m', 'SimpleHTTPServer', '9002'],
{ stdio: ['ignore', 'inherit', 'inherit' ] });
run.on('exit', (code) => {
console.log(`Child exited with code ${code}`);
});

Categories