I am learning to use electron js with python and I am using python-shell so I have the following simple python script:
import sys, json
# simple JSON echo script
for line in sys.stdin:
print(json.dumps(json.loads(line)))
and in my main.js:
let {PythonShell} = require('python-shell')
let pyshell = new PythonShell('/home/bassel/electron_app/pyapp/name.py', {mode : 'json'});
pyshell.send({name:"mark"})
pyshell.on('message', function (message) {
// received a message sent from the Python script (a simple "print" statement)
console.log("hi");
});
but the hi is not getting printed, what is wrong?
This problem can also occur when trying to suppress the newline from the end of print output. See Why doesn't print output show up immediately in the terminal when there is no newline at the end?.
Output is often buffered in order to preserve system resources. This means that in this case, the system holds back the Python output until there's enough to release together.
To overcome this, you can explicitly "flush" the output:
import sys, json
# simple JSON echo script
for line in sys.stdin:
print(json.dumps(json.loads(line)))
sys.stdout.flush() # <--- added line to flush output
If you're using Python 3.3 or higher, you may alternatively use:
import sys, json
# simple JSON echo script
for line in sys.stdin:
print(json.dumps(json.loads(line)), flush=True) # <--- added keyword
So I have a pretty simple python function sitting in the backend as follows:
def iterator():
for i in range(1000):
random_var = randrange(1000)
return jsonify({
"random_var" : random_var,
})
time.sleep(4)
When I run this function standalone, it runs for well a 1000 times very slowly generating a random number every 4 seconds. What I want is to connect this to html frontend via javascript and the code for that is as follows:
var Output_value = document.getElementById('Output_value');
$(function() {
$('#exe-btn').click(function(){
$.ajax({
url: '/display/',
success: function(data) {Output_value.innerHTML = data['random_var'];} });
}
);
});
This does work but not exactly as I expect it to.
Frontend
It displays the value once and then just stops and doesn't display it again unless I press the button again.
What I've researched so far:
The two potential candidates that I found to solve this included the setInterval and setTimeout functions in jquery, however the flaw with that approach is that they require the execution of the backend python function again and again, while what I require is that function to be executed only once.
What I want it to do
I want the backend iterator() to be executed only once and then the values of it to be returned to js so that the newest value is displayed on the html frontend and taking the place of the previous value.
What is happening right now is that the function in the backend is executed upon click but it stops streaming the output after returning one result.
The only way to do this is using websockets as Sergey said. The architecture for that is pretty simple though.
Keep an id in the html which will be used by the javascript to output the data it receives from the flask server. The flask server will use socket io and the javascript file will also use socket. The way it will work is that once the execute button on the frontend is pressed, the js calls an event in the backend which will receive it and then transmit out the data that you want to transmit. This is what the html code looks like:
<div class="Output">
<table>
<th ><h2>Python Library Output:</h2></th>
<th id="Output_value"> </th>
</table>
</div>
<div class= "execute_button">
<button id="exe-btn">Execute</button>
</div>
The exe-btn here is what we bind to jquery, which will call the module execution event in the backend. The JS code:
//Creating the event for execution of backend iterator script
//Setting up the event to be executed when the execute button is clicked and not otherwise
$(function() {
$('#exe-btn').click(function(){
socket.emit('module_trigger', {
data: 'Module event triggered'
})
}
);
});
socket.on( 'module_trigger_stream', function( msg ) {
console.log( 'Response 2')
console.log(msg['add'])
Output_value.innerHTML = msg['add']
//console.log(msg['message'])
}
);
Now the final step is to set up the handlers in the backend and also the method for creating the data. I use a simple random number generator which keeps emitting values after some time:
from flask import Flask, jsonify, render_template
from flask_socketio import SocketIO, send
import math
import time
#module imports
from random import randrange
import json
app = Flask(__name__,template_folder ='templates/')
app.config['SECRET_KEY'] = 'vnkdjnfjknfl1232#'
socketio = SocketIO(app)
#socketio.on('module_trigger')
def handle_module_trigger(jsons, methods=['GET','POST']):
print('Trigger successfully executed')
print(str(jsons))
for i in range(1000):
random_var = randrange(1000)
time.sleep(4)
print("The random variable is " + str(random_var))
out = {'add' : str(random_var)}
socketio.emit('module_trigger_stream',out)
#app.route("/",methods=['GET','POST'])
def render_output():
return render_template("index.html" )
if __name__ == "__main__":
socketio.run(app,debug=True)
I am trying to write into a json file through a python function. The python function dumps the python data structure into a json file using json.dumps funtion.
The file gets created as well as the python data structure in form of json object is present in the json file but when javascript function present inside the python function tries to open and read the object it fails.
I get the following error: Not found file_name.json
I am pretty sure that the file is indeed present.
def func(request):
arr = [[]]
message = ''
arr[0].append('Hello')
arr[0].append('There')
arr.append([])
arr[1].append('Good')
arr[1].append('Morning')
arr[1].append('!')
message = message + '<html><head><script type="text/javascript" src="outputjson.js"></script><script>function Hello(){alert(hello[1]);}</script></head>'
with open('outputjson.js', 'w') as fo:
jsonp_structure = "hello = "+json.dumps(arr)+" "
fo.write(jsonp_structure)
message = message + '<body><h1>This is shit and you know it</h1><input value="Click Bro" type="button" onclick="Hello();"></input></body></html>'
return HttpResponse(message)
I get the error stating: Not found: outputjson.js
Do I need to explicitly tell Django where to look for the file ?
keep the js file in the static folder and try something like this
from django.contrib.staticfiles.templatetags.staticfiles import static
url = static('outputjson.js')
and in
src="'+url+'"
with open('outputjson.js', 'r') as fo:
fo.read()
This should open the file and read it
I am having problem in calling a python function with angularjs $http request.
I am having a python function which is on server like this
import cgi, cgitb
data= cgi.FieldStorage()
name = data.getvalue("name");
age = data.getvalue("age");
def printinfo( name, age ):
print "Name: ", name
print "Age ", age
return name,age
and i've also included cgi and my javascript code is
angular.module('app1',[])
.controller('ctrl',['$scope','$http' ,function ($scope,$http) {
$scope.bin = 'examp';
$scope.go = function () {
var url = "http://localhost/dump/test/test.py";
var bad =$http({
url :url ,
method:'POST',
data:{"name":"kumar" , "age":21}
}).success(function(data){
alert("working");
});
}
}])
and my javascript code is able to make a call to http://localhost/dump/test/test.py but it is shown as a document even when i included cgi in it ..
Please guide me and also can you guys tell me is it the right way to send the values to server ie can i invoke the function print info by just sending name and age or should i send the function name too. If yes let me know how can i pass it ..
Thanks in advance..
May be your webserver do not know how to handle .py files. You need to configure webserver to handle python. Try the below if it is not configured.
https://www.linux.com/community/blogs/129-servers/757148-configuring-apache2-to-run-python-scripts
But a more good approach is to create a web app using some python framework and expose urls via a web server. If you are interested in that then I would recommend you to learn flask python framework.
I'm trying to find out how to create a local connection between a Python server and a Javascript client using the JSON format for the data to be retrieved. Particularly, I need to make some queries on the HTML client side, send these queries to the server on JSON format and run them on the Python server side to search for data on a SQLite Database. And after getting the results from the database, send those results back to the client in JSON format too.
By now, I just can run the query on Python and code it on JSON like this:
import sqlite3 as dbapi
import json
connection = dbapi.connect("C:/folder/database.db")
mycursor = connection.cursor()
mycursor.execute("select * from people")
results = []
for information in mycursor.fetchall():
results += information
onFormat = json.dumps(results)
print(onFormat)
I know this code does something alike (in fact it runs), because it calls a service on a server which returns data in JSON format (but the server in this example is NOT Python):
<html>
<head>
<style>img{ height: 100px; float: left; }</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div id="images"></div>
<script>
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?",
{
tags: "mount rainier",
tagmode: "any",
format: "json"
},
function(data) {
$.each(data.items, function(i,item){
$("<img/>").attr("src", item.media.m).appendTo("#images");
if ( i == 3 ) return false;
});
});</script>
</body>
</html>
What I need is to know how should I run (locally) the python program to be an available running web-service and how should be the Javascript to retrieve the data from the python server.
I've looking for this on internet everywhere but I didn't find this answer anywhere because the only answers they give are on how to code JSON inside Python or inside Javascript but not connecting both. Hope somebody can help me on this!!!
Here's a "hello world" example of a flask web-application that can serve static html and javascript files, search database using parameter from a javascript request, and return results to javascript as json:
import sqlite3
from flask import Flask, jsonify, g, redirect, request, url_for
app = Flask(__name__)
#app.before_request
def before_request():
g.db = sqlite3.connect('database.db')
#app.teardown_request
def teardown_request(exception):
if hasattr(g, 'db'):
g.db.close()
#app.route('/')
def index():
return redirect(url_for('static', filename='page.html'))
#app.route('/json-data/')
def json_data():
# get number of items from the javascript request
nitems = request.args.get('nitems', 2)
# query database
cursor = g.db.execute('select * from items limit ?', (nitems,))
# return json
return jsonify(dict(('item%d' % i, item)
for i, item in enumerate(cursor.fetchall(), start=1)))
if __name__ == '__main__':
app.run(debug=True, host='localhost', port=5001) # http://localhost:5001/
else:
application = app # for a WSGI server e.g.,
# twistd -n web --wsgi=hello_world.application --port tcp:5001:interface=localhost
The database setup code is from Using SQLite 3 with Flask.
static/page.html and static/json-jquery.js files are from Ajax/jQuery.getJSON Simple Example, where the javascript code is modified slightly to pass a different url and nitems parameter:
$(document).ready(function(){
$('#getdata-button').live('click', function(){
$.getJSON('/json-data', {'nitems': 3}, function(data) {
$('#showdata').html("<p>item1="+data.item1+" item2="+data.item2+" item3="+data.item3+"</p>");
});
});
});
Your question amounts to "how do I make this python into a webservice".
Probably the most lightweight ways to do that are web.py and flask. Check them out.
If this is getting bigger, consider django with tastypie - that's a simple way to make a json-based api.
Update: Apparently, there is also a python-javascript RPC framework called Pico, to which Felix Kling is a contributor. The intro says:
Literally add one line of code (import pico) to your Python module to
turn it into a web service that is accessible through the Javascript
(and Python) Pico client libararies.
I found finally an easier way than Flask. It's a Python framework called Bottle You only need to download the library from the official web site and put all its files in your working directory in order to import the library. You can also install it using the setup python program included to avoid carrying with the sourcecode everywhere. Then, for making your Web Service Server you can code it like this:
from bottle import hook, response, route, run, static_file, request
import json
import socket
import sqlite3
#These lines are needed for avoiding the "Access-Control-Allow-Origin" errors
#hook('after_request')
def enable_cors():
response.headers['Access-Control-Allow-Origin'] = '*'
#Note that the text on the route decorator is the name of the resource
# and the name of the function which answers the request could have any name
#route('/examplePage')
def exPage():
return "<h1>This is an example of web page</h1><hr/><h2>Hope you enjoy it!</h2>"
#If you want to return a JSON you can use a common dict of Python,
# the conversion to JSON is automatically done by the framework
#route('/sampleJSON', method='GET')
def mySample():
return { "first": "This is the first", "second": "the second one here", "third": "and finally the third one!" }
#If you have to send parameters, the right sintax is as calling the resoure
# with a kind of path, with the parameters separed with slash ( / ) and they
# MUST to be written inside the lesser/greater than signs ( <parameter_name> )
#route('/dataQuery/<name>/<age>')
def myQuery(name,age):
connection= sqlite3.connect("C:/folder/data.db")
mycursor = connection.cursor()
mycursor.execute("select * from client where name = ? and age= ?",(name, age))
results = mycursor.fetchall()
theQuery = []
for tuple in results:
theQuery.append({"name":tuple[0],"age":tuple[1]})
return json.dumps(theQuery)
#If you want to send images in jpg format you can use this below
#route('/images/<filename:re:.*\.jpg>')
def send_image(filename):
return static_file(filename, root="C:/folder/images", mimetype="image/jpg")
#To send a favicon to a webpage use this below
#route('/favicon.ico')
def favicon():
return static_file('windowIcon.ico', root="C:/folder/images", mimetype="image/ico")
#And the MOST important line to set this program as a web service provider is this
run(host=socket.gethostname(), port=8000)
Finally, you can call the REST web service of your Bottlepy app on a Javascript client in this way:
var addr = "192.168.1.100"
var port = "8000"
function makeQuery(name, age){
jQuery.get("http://"+addr+":"+port+"/dataQuery/"+ name+ "/" + age, function(result){
myRes = jQuery.parseJSON(result);
toStore= "<table border='2' bordercolor='#397056'><tr><td><strong>name</strong></td><td><strong>age</strong></td></tr>";
$.each(myRes, function(i, element){
toStore= toStore+ "<tr><td>"+element.name+"</td><td>" + element.age+ "</td></td></tr>";
})
toStore= toStore+ "</table>"
$('#theDataDiv').text('');
$('<br/>').appendTo('#theDataDiv');
$(toStore).appendTo('#theDataDiv');
$('<br/>').appendTo('#theDataDiv');
})
}
I hope it could be useful for somebody else