D3.js with Python, rendering a blank page - python-3.x

Setup: I'm trying to create a simple D3 js demo with Python 3 handling requests. Following the steps below I expected to see an error or some kind of HTML generated when I click on my html page with my d3 method. Instead, I receive a blank page.
1) Create custom HTTPRequestHandler class to handle GET requests
from http.server import BaseHTTPRequestHandler, HTTPServer
import os
class HTTPRequestHandler(BaseHTTPRequestHandler):
#handle GET command
def do_GET(self):
rootdir = r'C:\Current_Working_Directory' #file location
try:
if self.path.endswith('.json'):
f = open(rootdir + self.path, 'rb') #open requested file
#send code 200 response
self.send_response(200)
#send header first
self.send_header('Content-type','applicaon/json')
self.end_headers()
#send file content to client
self.wfile.write(f.read())
f.close()
return
except IOError:
self.send_error(404, 'file not found')
def run():
print('http server is starting...')
#ip and port of server
server_address = ('127.0.0.1', 80)
httpd = HTTPServer(server_address, HTTPRequestHandler)
print('http server is running...')
httpd.serve_forever()
if __name__ == '__main__':
run()
2) Save above file as server.py and run python server.py and create some dummy json data stored in data.json in $rootdir and create d3.html:
<!DOCTYPE html>
<html>
<head>
<title>D3 tutorial 10</title>
<script src=”http://d3js.org/d3.v3.min.js”></script>
</head>
<body>
<script>
d3.json(“dummy.json”, function (error,data) {
if (error) return console.warn(error);
console.log(data)
});
</script>
</body>
</html>
4) Open up web page expecting to see an error or some indication that d3 has sent the GET request to the server, but get a blank page.

Related

reload html elements flask

Hello everyone!,
so I was building a flask app that displays the current time.The time does display on the webpage as intended.But,the thing is that I have the reload the page manually for the time to update.But I want the time to update on itself.Here is my python file containing the code to the website:
from flask_sqlalchemy import SQLAlchemy
import time
from flask import render_template , Flask
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
#app.route('/')
def index():
while True:
global time
time1 = time.time()
global time2
time2 = time.ctime(time1)
return render_template('index.html' , time3 = time2)
if __name__ == '__main__':
app.run(debug = True)
and here is my HTML code for the website:
<!DOCTYPE HTML>
<head>
</head>
<body>
<h1>{{time3}}</h1>
</body>
Can anyone help me out plz?
As I know, you can't do this only using html and python, you need to use Javascript or any other client side language. If time info will be served by python(from server) you can do it like ;
Html and JavaScript code:
<!DOCTYPE HTML>
<html>
<body>
<h>Time: </h>
<span id="time"></span>
</body>
<script type=text/javascript>
function timeClock()
{
var xhr = new XMLHttpRequest();
xhr.open("GET", "{{ url_for('time_info') }}", true);
xhr.onload = function()
{
if(this.status = 200)
{
time.innerHTML = this.response;
}
else
{
console.error(xhr);
}
};
xhr.send(null);
}
setInterval(timeClock, 1000);
</script>
</html>
Flask code:
from flask import Flask,render_template,jsonify
import time
app = Flask(__name__)
#app.route("/")
def main_page():
return render_template("index.html")
#app.route("/time_info",methods=['GET'])
def time_info():
return jsonify(time.ctime())
if __name__ == "__main__":
app.run(debug=True)
timeClock() func will send GET reqest to the server every second and python will get this request and it will send time.ctime() output to the client. Client will get this info and then it will update the html span element

How to use Pyramid to host static files at an absolute path on my computer?

I created a simple Pyramid app from the quick tutorial page here that has the following files relevant to the question:
tutorial/__init__.py:
from pyramid.config import Configurator
def main(global_config, **settings):
config = Configurator(settings=settings)
config.include('pyramid_chameleon')
config.add_route('home', '/')
config.add_route('hello', '/howdy')
config.add_static_view(name='static', path='tutorial:static')
config.scan('.views')
return config.make_wsgi_app()
tutorial/views/views.py:
from pyramid.view import (
view_config,
view_defaults
)
#view_defaults(renderer='../templates/home.pt')
class TutorialViews:
def __init__(self, request):
self.request = request
#view_config(route_name='home')
def home(self):
return {'name': 'Home View'}
#view_config(route_name='hello')
def hello(self):
return {'name': 'Hello View'}
tutorial/templates/image.pt:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Quick Tutorial: ${name}</title>
<link rel="stylesheet"
href="${request.static_url('tutorial:static/app.css') }"/>
</head>
<body>
<h1>Hi ${name}</h1>
<img src="${filepath}">
</body>
</html>
I want to add a URL route to my app such that when a user goes to www.foobar.com/{filename} (for example: www.foobar.com/test.jpeg), the app would show the image from the absolute path /Users/s/Downloads/${filename}on the server, as shown in the file tutorial/templates/image.pt above.
This is what I tried:
In the file tutorial/__init__.py, added config.add_route('image', '/foo/{filename}').
In the file development.ini, added the setting image_dir = /Users/s/Downloads.
In the file tutorial/views/views.py, ddded the following view image:
#view_config(route_name='image', renderer='../templates/image.pt')
def image(request):
import os
filename = request.matchdict.get('filename')
filepath = os.path.join(request.registry.settings['image_dir'], filename)
return {'name': 'Hello View', 'filepath': filepath}
However this does not work. How can I get absolute paths for assets working with Pyramid?
filepath needs to be a url if you're expecting to put it as the src attribute in an img tag in your HTML. The browser needs to request the asset. You should be doing something like request.static_url(...) or request.route_url(...) in that image tag. This is the URL generation part of the problem.
The second part is actually serving file contents when the client/browser requests that URL. You can use a static view to support mapping the folder on disk to a URL structure in your application in the same way as add_static_view is doing. There is a chapter on this in the Pyramid docs at https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/assets.html. There is also a section specifically on using absolute paths on disk. You can register multiple static views in your app if you feel it's necessary.

background task does not emit

There are many tutorials available for Flask and SocketIO, I could not find any for a simple threaded approach that I understood. But I did read and followed many of them.
I'd like to show my Python application on a web page using websockets so it's kind-of real-time monitoring. This is me trying to understand how to implement this.
The code I currently have is working for except the emit part. There does not seem to be any transfer of data. I'd like to know why.
The socket.on('tingeling' ... is not being triggered.
My Python code, mostly taken from https://codeburst.io/building-your-first-chat-application-using-flask-in-7-minutes-f98de4adfa5d
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = ''
socketio = SocketIO(app)
thread = None
def counter():
print("counter ding")
counting = 0
while True:
counting += 1
socketio.sleep(2)
socketio.emit('tingeling', counting, namespace='')
print(f"Counter: {counting}")
#app.route('/')
def sessions():
print('route')
return render_template('index.html')
#socketio.on('my event')
def connected(data):
print('my event')
#socketio.on('connect')
def starten():
print("connect")
socketio.emit('tingeling', 'start')
global thread
if thread is None:
print('thread ding')
thread = socketio.start_background_task(target=counter())
return render_template('index.html')
if __name__ == '__main__':
socketio.run(app, debug=True)
And my HTML template:
<!DOCTYPE html>
<html lang="en">
<head>
<title>fristi</title>
</head>
<body>
<h3 style='color: #ccc;font-size: 30px;'>waiting</h3>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script>
<script type="text/javascript">
var socket = io.connect('http://' + document.domain + ':' + location.port);
console.log('doet iets')
socket.on( 'connect', function() {
socket.emit( 'my event', {
data: 'User Connected'
})
})
socket.on('tingeling', function(msg) {
console.log('iets komt binnen')
console.log(msg)
})
</script>
</body>
</html>
My error is on the line: thread = socketio.start_background_task(target=counter())
There I reference the function to run as a background task but I use the notation with () and that is not allowed because is runs the function and does not provide the start_background_task with a reference to this function.

python socket io client emit got an unexpected keyword argument 'wait'

I am using RPI, VPS, and socket io. I want to create a website where a user can go to click a button and get a pic from the pi.
I wrote the server and the client applications in python.
the server uses socketio + flask
server.py
from flask import Flask, request, render_template
from flask_socketio import SocketIO, rooms, join_room, leave_room
app = Flask(__name__, static_url_path='/static')
app.config['SECRET_KEY'] = 'secret!'
sio = SocketIO(app)
#app.route('/')
def index():
"""Serve the client-side application."""
with open('index.html') as f:
return f.read()
# return app.send_static_file('index.html')
#sio.on('connect')
def connect():
print('Connected:')
#sio.on('join')
def on_join(room):
join_room(room)
print(request.sid + ' joined room ' + room )
#sio.on('leave')
def on_leave(room):
leave_room(room)
print(request.sid + ' left room ' + room )
#sio.on('message')
def handle_json(message):
# print('Received json: ')
# print(message)
room = rooms(request.sid)[0]
print('Forwarding to room:', room)
sio.send(message, room=room, skip_sid=request.sid, json=True)
if __name__ == '__main__':
sio.run(app, host= "142.11.210.25", port = 80)
rpi_client.py
import io
import time
import picamera
import socketio
import base64
sio = socketio.Client()
# Specify the room
room = 'cam_1'
socket_url = 'http://142.11.210.25:80/'
def capture_b64_image():
# Create an in-memory stream
image_stream = io.BytesIO()
# Capture image
with picamera.PiCamera() as camera:
# Camera warm-up time
time.sleep(2)
camera.capture(image_stream, 'jpeg')
# Encode the image
image_bytes = image_stream.getvalue()
return base64.b64encode(image_bytes).decode()
#sio.on('connect')
def on_connect():
print('Connection established')
sio.emit('join', room)
#sio.on('json')
def on_message(data):
print('Received message:', data)
encoded_image = capture_b64_image()
print( len(encoded_image) )
sio.send({'image': encoded_image})
#sio.on('disconnect')
def on_disconnect():
print('Disconnected from server')
sio.connect(socket_url)
sio.wait()
index.html
<!DOCTYPE html>
<html>
<head>
<title>SocketIO Demo</title>
</head>
<body>
<img id="image-preview" src="" />
<button id='cam_click'>Take photo</button>
<script
src="http://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous"></script>
<script src="/static/js/socket.io.js"></script>
<script>
var socket = io('/');
var room = 'cam_1';
function bytes2ascii(bytes) {
var str = '';
for(var i = 0; i < bytes.length; i++) {
str += String.fromCharCode(bytes[i]);
}
return str;
}
socket.on('connect', function() {
console.log(11);
socket.emit('join', room);
});
socket.on('json', function (data) {
console.log('Received:');
console.log(data);
// $('#cam_content').html(data.image);
//var encoded_image = bytes2ascii(new Uint8Array(data.image) );
var encoded_image = data.image
$('#image-preview').attr('src', `data:image/png;base64,${encoded_image}`);
});
$(document).ready(function() {
console.log('Ready...');
$('#cam_click').click(function() {
socket.send('image');
});
});
</script>
</body>
</html>
when i run the server and the rpi client, I get connection established, and when I click on the button to take photo in the index.html, the server fowrards to room1 and I get that on the rpi client and it takes a pic, but then it crashes when its sending the pic and it gives me
TypeError: emit() got an unexpected keyword argument 'wait'
here is the error I get(rpi client) when I run the codes.
Connection established
Received message: image
996008
Exception in thread Thread-5:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.5/dist-packages/socketio/client.py", line 514, in _handle_eio_message
self._handle_event(pkt.namespace, pkt.id, pkt.data)
File "/usr/local/lib/python3.5/dist-packages/socketio/client.py", line 413, in _handle_event
r = self._trigger_event(data[0], namespace, *data[1:])
File "/usr/local/lib/python3.5/dist-packages/socketio/client.py", line 455, in _trigger_event
return self.handlers[namespace][event](*args)
File "rpi_client2.py", line 41, in on_message
sio.send({'image': encoded_image})
File "/usr/local/lib/python3.5/dist-packages/socketio/client.py", line 296, in send
callback=callback, wait=wait, timeout=timeout)
TypeError: emit() got an unexpected keyword argument 'wait'
I installed python-socketio[client] as instructed.
What could be causing the error and whats the workaround? thank you and have a nice day!
According to the python-socketio doc, https://python-socketio.readthedocs.io/en/latest/client.html#emitting-events:
For convenience, a send() method is also provided. This method accepts a data element as its only argument, and emits the standard message event with it:
sio.send('some data')
Therefore, you can change:
sio.send({'image': encoded_image})
to:
sio.emit('message', {'image': encoded_image})

Flask-socketio sending payloads one at a time

I have the following Python script which is using Flask-socketio
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from time import sleep
app = Flask(__name__)
app.config['SECRET_KEY'] = 'P#ssw0rd'
socketio = SocketIO(app)
#app.route('/')
def index():
return render_template('index.html')
#socketio.on('connect')
def on_connect():
payload1 = 'Connected!!!'
payload2 = 'Doing thing 1'
payload3 = 'Doing thing 2'
emit('send_thing', payload1, broadcast=True)
sleep(2)
emit('send_thing', payload2, broadcast=True)
sleep(2)
emit('send_thing', payload3, broadcast=True)
if __name__ == '__main__':
socketio.run(app)
And here is the corresponding index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SocketIO Python</title>
</head>
<body>
<div id="my-div"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.js"></script>
<script>
(function init() {
var socket = io()
var divElement = document.getElementById('my-div')
socket.on('send_thing', function(payload) {
var dataElement = document.createElement('inner')
dataElement.innerHTML = payload
divElement.appendChild(dataElement)
})
})()
</script>
</body>
</html>
What I am trying to achieve is that when a client connects, it first says 'Connected!!!' and then 2 seconds later a new 'inner' element appears that says 'Doing thing 1' followed by 2 seconds later a new 'inner' element appears that says 'Doing thing 2' etc.
But what is happening is that when a client connects, it sends all 3 lines at the same time (after 4 seconds which is both sleep statements). This is the first time using SocketIO so I'm sure I've done something wrong.
When you use eventlet or gevent, the time.sleep() function is blocking, it does not allow any other tasks to run.
Three ways to address this problem:
Use socketio.sleep() instead of time.sleep().
Use eventlet.sleep() or gevent.sleep().
Monkey patch the Python standard library so that time.sleep() becomes async-friendly.

Resources