python-socketio icon indicating copy to clipboard operation
python-socketio copied to clipboard

Emit works in def connect but do not works in an if

Open Jey0707 opened this issue 3 years ago • 7 comments

Emit works in def connect but do not works in an if.

Steps to reproduce the behavior: This is my code:


sio = socketio.Server(cors_allowed_origins='*')
app = socketio.WSGIApp(sio)

@sio.event
def connect(sid, environ):
    print('connect ', sid)
    print(sio)
    sio.emit('login', {'email': '[email protected]', 'password':'opasw'}) #This works


@sio.on('logged')
def hello(sid, data):
    print(f'Login from: {sid} - {data}')


@sio.on('chrome_connected')
def connected(sid, data):
    print(f'Chrome connected: {data["email"]} - {sid}')
    Ikigai.chrome_connected = {data["email"] : sid}

@sio.event
def my_message(sid, data):
    print('message ',sio, data)

@sio.event
def disconnect(sid):
    print('disconnect ', sid)
    



def socketStart():
    print("Starting server")
    eventlet.wsgi.server(eventlet.listen(('', 5000)), app, log_output=False)



if __name__ == '__main__':

    t = Thread(target=socketStart, args=())
    t.start()
    

    log('Starting session for [email protected]')

   
    sio.emit('login', {'email': '[email protected]', 'password':'opasw'}) #This do not work
    

Expected behavior Reading documentation: Socket.IO is a bidirectional protocol, so at any time the server can send an event to its connected clients

Logs I tryed to print(sio) to make sure if it is the same object and it's the same obj

Additional context Added #this works and #this do not work in code to help understanding

Jey0707 avatar Jul 18 '22 12:07 Jey0707

Who do you expect will receive the sio.emit call that you placed at the bottom of the script? This call runs right when the server is starting. At that point there are no connected clients that can receive your event. I also find it strange that the server is sending login credentials to clients, but I assume this is just a quick test that you are doing.

As an additional problem, you are mixing threads with eventlet greenlets, and that is not going to work. If you use threads in an eventlet app, all the greenlet activity must happen on a single thread, you cannot emit from a main thread if the eventlet thread is some other thread that you started.

miguelgrinberg avatar Jul 18 '22 12:07 miguelgrinberg

Thank for your fast reply Miguel.

I have connected chrome extention to socket.io to communicate between Python code and chrome extention in chrome who make a login on browser

Just like I told you the call I expect the receives the chrome extention (javascript)

If I’m not mistaken, it should continue to be connected because I initialized the server in a thread.

I enclose a log image of the events

image

Jey0707 avatar Jul 18 '22 12:07 Jey0707

You are ignoring my comment regarding eventlet.

Also the log that you pasted does not agree with the code. There is no log message in the code that prints "starting session for user".

miguelgrinberg avatar Jul 18 '22 12:07 miguelgrinberg

Sorry Miguel, I didn't see it. Now I read. So the best way to do what I want is starting an async server?

Jey0707 avatar Jul 18 '22 12:07 Jey0707

Your server is async already (eventlet is an async framework). What you can't do is use threads mixed with it. All the activity must be contained in the one thread that hosts the server.

In my opinion you need to rethink what you are doing. If you want to emit to a connected client, then wait until the client connects, then emit. Emitting out of nowhere is not a good design, as you have no way to make sure the client is there to receive the data.

miguelgrinberg avatar Jul 18 '22 13:07 miguelgrinberg

Thank you for your advice Miguel!

There is no way to call it from there? Because I want to start first a chrome driver with the chrome extention loaded and then connect. I want to do it with multiple chrome drivers in different time, so I need to call it in different part of code

Jey0707 avatar Jul 18 '22 13:07 Jey0707

@VitoFarella I'm really not sure how else to explain. You are putting eventlet with the server in thread 2. You are asking me how to emit from thread 1. I explained that eventlet is async, you cannot mix it with threads. If you are not going to change anything, then it cannot be done. If you want to use threads, then drop eventlet. If you want to keep using eventlet, then emit from the eventlet thread.

In any case, this design is flawed, and you seem to be ignoring this as well. You can't expect a reliable solution when you start the server and immediately emit to your connected clients. More than likely your client(s) will not have time to connect and the emit will not be sent to anyone.

miguelgrinberg avatar Jul 18 '22 13:07 miguelgrinberg