socket.emit delay does not work in flask_SocketIO - python

I have flask_socketIO Python server:
from flask import Flask
from flask_socketio import SocketIO
import time
app = Flask(__name__)
sio = SocketIO(app)
#sio.on("client_connect")
def client_connect():
sio.emit("test")
time.sleep(1) # Should be computationally complex code: for i in range(1000000): ...
sio.emit("test")
sio.run(app)
And socketio Python client:
from socketio import Client
import time
sio = Client()
sio.connect("http://localhost:5000")
#sio.event
def test():
print("TEST socket message", time.time())
sio.emit("client_connect")
So these steps should be performed:
Client connect to server
Client sends client_connect message to server
Server sends test message to client
Server waits 1 s
Server sends another test message to client
1 and 2 work, but instead of next steps server first waits 1 s and than sends test message twice in (almost) same time. So output of client is (both messages was received in the same second):
TEST socket message 1595397405
TEST socket message 1595397405
Am I doing something wrong?

Related

How can i invoke a flask endpoint directly from code without using requests

Hey everyone I was tasked a few days ago to create an API style application that listens over a TCP socket for some commands then return some responses mainly success/failures (i know it's dumb but it's the client request) since I have some validation/database stuff I thought of flask directly but I am still stuck on how I am going to invoke the specific endpoints in code directly. here is a small snippet on how I am imagining things would be
from flask import Flask
import threading
data = 'foo'
app = Flask(__name__)
#app.route("/SomeCommand")
def SomeCommand():
return { 'Some' : 'Response'}
def flaskThread():
app.run()
def TcpListenner():
# logic that listens over tcp socket then invoks the flask app
# I was thinking about calling app.something() from here
pass
if __name__ == "__main__":
flaskApp = threading.Thread(target=flaskThread)
flaskApp.start()
listenner = threading.Thread(target=TcpListenner)
listenner.start()
any help/ideas would be much appreciated, thank you
You can use flask_socketio with which the flask app and socket i.e. tcp listener both start together...
Based on what I've understood, you can do something like this:
That the client will first make a connection to the flask socket.
Then, to send a command to the flask app, the client will send a message to the flask socket with the command in its message.
The flask socket will be listening for messages. So when it receives a message for the specific command, then it emits a response based on that command to the socket which will then be received by the client.
Below is an example code for the flask socket app:
import eventlet
eventlet.monkey_patch()
from flask import Flask
from flask_socketio import SocketIO, send, emit
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*", logger=True, engineio_logger=True)
# other flask APIs can come here and can be called by the client...
def someCommandOneResponse(): # function that sends response to client when flask socket gets command 1
commandOneResponse = 'Success'
socketio.emit('message', commandOneResponse)
def someCommandTwoResponse(): # function that sends response to client when flask socket gets command 2
commandTwoResponse = 'Failure'
socketio.emit('message', commandTwoResponse)
#socketio.on('message') # when any command is received on the socket from the client
def handleMessage(cmd):
print('\nCommand Received: ' + cmd + '\n')
if( cmd == 'SomeCommand1' ): # if the client has sent a message for command 1
print('Got Some Command 1')
someCommandOneResponse()
elif( cmd == 'SomeCommand2' ): # if the client has sent a message for command 2
print('Got Some Command 2')
someCommandTwoResponse
send(cmd, broadcast=True)
if __name__ == '__main__':
socketio.run(app, port=3000) # starts the flask socket (tcp listener) as well as the flask app

How can i properly use circular imports in python

Context: I have a websocket 'server.py' and a script that executes some tasks: 'worker.py'. I want to use the functions in server.py to send the results from that task in worker.py. But the thing is, when a client requests the worker to send results, i need to use a function from worker.py. How can I avoid circular dependies in this situation?
Server.py:
import eventlet
#eventlet.monkey_patch()
import socketio
from flask import Flask
from flask_cors import CORS
#The Worker file
import worker
sio = socketio.Server(cors_allowed_origins='http://localhost:8100')
#sio.on('connect')
def connectHandler(sid, environ):
print('[INFO] Incoming connection from: ' + environ['REMOTE_ADDR'])
sio.emit('response', {'data' : 'Connection established, you can now request classifications by firing the "requestClassification" event.'})
#sio.on('disconnect')
def disconnectHandler(sid):
print('disconnect ', sid)
#sio.on('requestClassification')
def requestHandler(data):
print('[INFO] recieved request to classify')
print(data)
#using a function in the worker module
worker.someFunc()
eventlet.wsgi.server(eventlet.listen(('127.0.0.1', 8080)), app)
worker.py:
import server
def work():
while True:
result = doSomeTask()
print(f'sending result: {str(i)}')
server.sio.emit('result', {'data' : result})
server.sio.sleep(1)
How can i properly use the imports without defining sio (the server) twice for example?

How to connect/listen to nsqd from a webserver

So I have a simple flask server and wanted to listen to nsqd,(My nsqd and nsqlookupd dockers are running fine.) I'm using gnsq from python as a tool to achieve that
server.py:
from flask import Flask
import gnsq
consumer = gnsq.Consumer('test_topic', 'test_channel', '0.0.0.0:4161')
#consumer.on_message.connect
def handler(consumer, message):
print ('got message:', message.body)
consumer.start()
app = Flask(__name__)
#app.route("/")
def hello():
return "Flasky"
and when I run the server all I get is
[0.0.0.0:4161] connection failed (NSQSocketError(57, 'Socket is not connected'))
I tried changing ports as well but still persist.

Websocket listen continuously after receiving response in tornado

I'm working on a websocket client listening to a tornado server.
Once the client receives a message from server, the client is exiting silently.
Following is the code I've implemented.
#!/usr/bin/python
import tornado.websocket
from tornado import gen
import requests
#gen.coroutine
def test_ws():
client = yield tornado.websocket.websocket_connect("ws://localhost:8888/subscribe/ports")
msg = yield client.read_message()
print(msg)
if __name__ == "__main__":
loop = tornado.ioloop.IOLoop()
loop.run_sync(test_ws)
The client is running until it receives the first message from server. But I want to run indefinitely.
Am I missing something?
Use a loop:
#gen.coroutine
def test_ws():
client = yield tornado.websocket.websocket_connect("ws://localhost:8888/subscribe/ports")
while True:
msg = yield client.read_message()
print(msg)

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