Background
I'm making a web dashboard with flask/python. My program's main task is a loop that sends some information to a javascript script in my index.html (through flask-socketio), every 3 seconds. The javascript uses socketio to constantly listen for this info, and when it receives it, it updates an HTML element to show the new data, using ajax/jquery to only reload the relevant div.
Issue
When you start flask it warns you that the default flask server is "a development server for development use only". So I started using gevent, but this had a weird side effect: the webpage became slow at updating the HTML element, even though the js was definitely receiving the messages through socketio, as it was printing the console.log messages I made it do.
The flask development server worked fine; it would update the HTML element every 3 seconds as it should. But when I switched to gevent, there started being random gaps between the updates, instead of the required 3s. It would do random things like having a gap of 2 seconds at some points but then 10 seconds, and then 5 seconds, etc.
Code
main.py
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import threading
import time
from queue import Queue
import random
app = Flask(__name__)
socket = SocketIO(app)
def main():
q = Queue()
threading.Thread(target=update_dash, args=(q,), daemon=True).start() #thread for updating the dash
threading.Thread(target=gen_numbers, args=(q,), daemon=True).start() #threading for the flask application
socket.run(app, host="0.0.0.0")
def gen_numbers(q):
while True:
time.sleep(3)
print("----------------------")
print("sending to update_dash")
x = random.randint(1, 100)
q.put(x) #send the data to the update_dash thread
def update_dash(q):
while True:
if not q.empty(): #received some data from main()
data = q.get() #retrieve the data that main() sent
msg = f"random number sent by main thread: {data}"
print("sending data to the socket")
socket.emit("update", msg, broadcast=True)
print("data sent!")
time.sleep(0.5)
@app.route("/")
def index():
return render_template("index.html")
if __name__ == "__main__":
main()
index.html
<!doctype html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.js"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
var socket = io.connect("http://" document.domain ":" location.port);
socket.on("connect", function() {
console.log("connected");
});
socket.on("update", function(msg) {
console.log("received");
$("#main").text(msg);
});
});
</script>
</head>
<body>
<div id="main">
initial message, will be updated every 3s by the js script
</div>
</body>
</html>
I have researched this problem, and an answer I found suggested that the webpage will use polling instead of websocket protocol if you don't have gevent-websockets installed (as well as gevent itself). However I tried this but I'm still getting the same issues. (I also tried installing gevent-eventemitter too)
If anyone can tell me why gevent makes the page updates sporadic and slow, i would be very grateful
Thank you
CodePudding user response:
I solved this by adding
from gevent import monkey
monkey.patch_all()
at the very start of my program.
Thank you to @Miguel Grinberg for this solution!