background threads in flask - python

I'm trying to run a function in the background as a thread in flask, but the whole server just stops.
from flask import Flask
from flask_socketio import SocketIO
from flask_cors import CORS
from threading import Thread
import time
app = Flask(__name__)
CORS(app)
app.debug = True
socketio = SocketIO(app, cors_allowed_origins="*")
number = 0
def rising_number():
global number
while True:
number = number + 1
time.sleep(1)
set_number = Thread(target=rising_number)
set_number.start()
def send_number():
while True:
socketio.emit('message', number)
time.sleep(0.1)
#socketio.on('connect')
def connection():
send_thread = Thread(target=send_number)
send_thread.start()
socketio.run(app,port=5000,host='0.0.0.0')
I'm trying to make the rising_number function run in the background, so the number displayed on the frontend will be the same for everyone on the website.

Related

How do i run a Python script on a dynamic webpage with Flask and Socketio?

I'm trying to use Flask and SocketIO, i found this example where some random numbers are printed dynamically in real time on a webpage.
from flask_socketio import SocketIO, emit
from flask import Flask, render_template, url_for, copy_current_request_context
from random import random
from time import sleep
from threading import Thread, Event
__author__ = 'slynn'
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
app.config['DEBUG'] = True
#turn the flask app into a socketio app
socketio = SocketIO(app)
#random number Generator Thread
thread = Thread()
thread_stop_event = Event()
class RandomThread(Thread):
def __init__(self):
self.delay = 1
super(RandomThread, self).__init__()
def randomNumberGenerator(self):
"""
Generate a random number every 1 second and emit to a socketio instance (broadcast)
Ideally to be run in a separate thread?
"""
#infinite loop of magical random numbers
print("Making random numbers")
while not thread_stop_event.isSet():
number = round(random()*10, 3)
print(number)
socketio.emit('newnumber', {'number': number}, namespace='/test')
sleep(self.delay)
def run(self):
self.randomNumberGenerator()
#app.route('/')
def index():
#only by sending this page first will the client be connected to the socketio instance
return render_template('index.html')
#socketio.on('connect', namespace='/test')
def test_connect():
# need visibility of the global thread object
global thread
print('Client connected')
#Start the random number generator thread only if the thread has not been started before.
if not thread.isAlive():
print("Starting Thread")
thread = RandomThread()
thread.start()
#socketio.on('disconnect', namespace='/test')
def test_disconnect():
print('Client disconnected')
if __name__ == '__main__':
socketio.run(app)
I have a Python script which connects to a Websocket, receives data and prints this data.
import websocket
from bitmex_websocket import Instrument
from bitmex_websocket.constants import InstrumentChannels
from bitmex_websocket.constants import Channels
import json
websocket.enableTrace(True)
channels = [
InstrumentChannels.trade,
]
XBTUSD = Instrument(symbol='XBTUSD',
channels=channels)
XBTUSD.on('action', lambda msg: test(msg))
def test(msg):
parsed = json.loads(json.dumps(msg))
print(parsed)
XBTUSD.run_forever()
I now want to print this data on my webpage, i tried to "merge" these two scripts but apparently i can't, because to run the Websocket connector i have to run XBTUSD.run_forever(), which will start the process but it won't run the rest of the code, including the Flask part which generates the webpage, so only one at time can run.
Is there a way to make the Websocket connector communicate with the Flask/Socketio part so that the data from the Websocket connector is printed on the webpage?

How to display the data in browser?

I want to send some data(hello world) using python socket io client to flask socket io...but nothing is displayed in browser
this is my client code
from socketIO_client import SocketIO, LoggingNamespace
def on_aaa_response(args):
print('on_aaa_response', args['data'])
socketIO = SocketIO('127.0.0.1', 5000)
socketIO.on('aaa_response', on_aaa_response)
socketIO.emit('aaa')
socketIO.wait(seconds=1)
this is my flask code
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#socketio.on('aaa')
def test_connect():
print("Welcome, aaa received")
emit('aaa_response', {'data': 'Server'})
#app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
socketio.run(app)

Send WebSocket message from Flask view

I'm trying to make a Flask app that uses WebSockets. The example from Flask-sockets works but how would I send a message from a regular view?
Similarly to how Flask-SocketIO use .emit() and .send()-methods.
In the example below (from the Flask-Sockets example) I would for instance like to be able to broadcast a message from the hello-view.
from flask import Flask
from flask_sockets import Sockets
app = Flask(__name__)
sockets = Sockets(app)
#sockets.route('/echo')
def echo_socket(ws):
while not ws.closed:
message = ws.receive()
ws.send(message)
#app.route('/')
def hello():
# How can I send a WebSocket message from here?
return 'Hello World!'
if __name__ == "__main__":
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
server.serve_forever()
You can use a global socket list of all client. Traverse all list and send message to all ws instance.
Example code;
from flask import Flask, render_template
from flask_sockets import Sockets
app = Flask(__name__)
sockets = Sockets(app)
ws_list = []
#sockets.route('/echo')
def echo_socket(ws):
ws_list.append(ws)
while not ws.closed:
message = ws.receive()
ws.send(message)
#app.route('/')
def hello():
# How can I send a WebSocket message from here?
return render_template('index.html')
#app.route('/send_message_to_all_client')
def broadcast():
for ws in ws_list:
if not ws.closed:
ws.send("broadcast message")
else:
# Remove ws if connection closed.
ws_list.remove(ws)
return "ok"
if __name__ == "__main__":
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
server.serve_forever()

"Connection was reset" error on flask server

I'm having an issue with dockers, I followed official docker tutorial to deploy a web app (and luckily a python/flask one) but when I tried to deploy my app when I come to the connection part it failed and reply "Connection was reset"
Code
import json
import threading
import thread
import io
from flask import Flask, render_template, request
from flask_socketio import SocketIO
# Global variables
app = Flask(__name__)
lock = threading.Semaphore(0)
IOCReplay.lock = lock
async_mode = None
socketio = SocketIO(app)
IOCReplay.socketio = socketio
#app.route("/")
def root():
return render_template('index.html')
#app.route("/dependencies")
def getDependencies():
data = ''
with open('./dependencies.json') as data_file:
data = json.load(data_file)
return json.dumps(data)
if __name__ == "__main__":
socketio.run(app, port=5000)
docker run -d -P guitest:1
6d95689601b8(...)
docker ps
CONTAINER ID IMAGE COMMAND
6d95689601b8 guitest:1 "python test.py"
CREATED STATUS PORTS NAMES
4 seconds ago Up 2 seconds 0.0.0.0:32771->5000/tcp loving_boyd
Dockerfile is OK.
Issue
And so when I'm logging into 0.0.0.0:32771 it says "Connection was reset"
I saw from docker FAQ that to correct this problem, i have to "change the service’s configuration on [my] localhost so that the service accepts requests from all IPs"
Ok I have solved all my problems! Thanks to #n2o
The problem was incorrect arguments for socketio.run(app)
Previous:
from flask import Flask, render_template, request
from flask_socketio import SocketIO
# Code here #
if __name__ == "__main__":
socketio.run(app, port=5000)
Fixed:
import os
from flask import Flask, render_template, request
from flask_socketio import SocketIO
# code here #
if __name__ == "__main__":
port = int(os.environ.get('PORT', 5000))
socketio.run(app, host='0.0.0.0', port=port)

Flask-socketio emit function in OSCserver thread

I am creating an Flask-socketio app, in which I want to send socket when an OSC message is received, in order to receive it into a web app thanks to socketio.js
from flask import Flask, render_template, copy_current_request_context, current_app
from flask_socketio import SocketIO, emit, send
from OSC import OSCClient, OSCMessage, OSCServer
import time, threading
app = Flask(__name__)
socketio = SocketIO(app)
client = OSCClient()
client.connect( ("localhost", 62345))
receive_address = ('localhost', 62346)
server = OSCServer(receive_address)
# simple callback functions
def answer_handler(addr, tags, stuff, source):
with app.app_context():
socketio.emit('tempo', 1)
# adding callback functions to listener
server.addMsgHandler("/puredata", answer_handler)
if __name__ == '__main__':
#Start OSCServer in extra thread
st = threading.Thread( target = server.serve_forever )
st.daemon = True
st.start()
print('OSC server is started')
socketio.run(app, host='0.0.0.0')
Even if I don't get error message, the socket is not receive from the javascript side, because the emit function is called in another thread, and there is conflicts with the request context.
I tried several things according to some other stackoverflow tickets :
socketio = SocketIO(app, async_mode='threading')
Adding this line before handler function
#copy_current_request_context
Or recreate a socketio instance into the callback
def answer_handler(addr, tags, stuff, source):
socketio_connection = SocketIO(app)
with app.app_context():
socketio_connection.emit('tempo', 1)
But none of these solution is working, and I need to integrate solve this 'context' problem into my thread.
Note that :
socketio.emit('tempo', 1)
is working great out of this thread , and received in the javascript part

Categories