Issue
In my project I am using flask_socketio as the server and socket.io-client with react as the client. My main.py(flask server) is constantly reading a log file(console.log) that is continuously updating. When the start button is clicked in the UI, the data of the log file is displayed, but as my log file is updated, the updated data is not displayed in the UI. I have to refresh the page or click the button again to see the updated data. I want the data of the log file to live stream on the UI with a button click. How to fix this?
flask code
from flask import Flask, jsonify
# Needed for localhost testing.
from flask_cors import CORS, cross_origin
from flask_socketio import SocketIO, emit
from time import sleep
import pdb
import json
app = Flask(__name__)
# Socket io setup.
app.config['SECRET_KEY'] = 'secret!'
# |cors_allowed_origins| is required for localhost testing.
socket = SocketIO(app, cors_allowed_origins="*")
# For localhost testing.
CORS(app)
@socket.on('event_stream', namespace='/logConsole')
def test_connect():
def generate():
fname = "./src/console.log"
with open(fname) as f:
yield f.read()
emit_data = next(generate())
socket.sleep(0)
emit('custom-server-msg', {'data': emit_data})
if __name__ == '__main__':
socket.run(app)
React code
import React from 'react'
import io from 'socket.io-client'
class App extends React.Component {
state = { startVar: true, setVar: false };
setSocketListeners() {
let socket = io.connect('ws://localhost:5000/logConsole');
socket.emit('event_stream', () => {
console.log("Websocket connected: " + socket.connected)
})
socket.on('custom-server-msg', (data) => {
console.log("Data received: " + data.data)
const setup_logs = data.data;
this.setState({ setup_logs });
})
}
render() {
return (
<div className="App">
<h1>Data from log file</h1>
<button type="button" onClick={() => this.setSocketListeners()}>Start</button>
<p>{this.state.setup_logs}</p>
</div>
);
}
}
export default App;
This is how my browser console looks like-->
And this is my backend console-->
Solution
In your flask code, if you want to stream continuously, the next() needs to be called in a loop, now either that can be done by putting a infinite loop with a sleep time,
@socket.on('event_stream')
def test_connect():
def generate():
fname = "./src/console.log"
with open(fname, "r+") as f:
yield f.read()
while True:
emit_data = next(generate())
socket.sleep(2)
emit('custom-server-msg', {'data':emit_data})
or else, if the log file is too being updated continuously, os.stat(FILE_NAME).st_mtime can be used which will check the time stamp of the file being updated, and if any change is there in the log file, next() will be called to stream it:
@socket.on('event_stream')
def test_connect():
cached_stamp = 0
def generate():
fname = "./src/console.log"
with open(fname, "r+") as f:
yield f.read()
while True:
stamp = os.stat('./src/console.log').st_mtime
if stamp != cached_stamp:
cached_stamp = stamp
emit_data = next(generate())
emit('topo-server-msg', {'data':emit_data})
Answered By - Bhavesh
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.