2016-01-03 17 views
15

Sono nella situazione in cui ricevo un messaggio dal client. All'interno della funzione che gestisce quella richiesta (@ socketio.on) voglio chiamare una funzione in cui è svolto un lavoro pesante. Ciò non dovrebbe comportare il blocco del thread principale e si pensa che il client venga informato una volta terminato il lavoro. Così inizio un nuovo thread.Python - Flask-SocketIO invia messaggio dalla discussione: non funziona sempre

Ora si verifica un comportamento davvero strano: Il messaggio non raggiunge mai il client. Tuttavia, il codice raggiunge quel punto particolare in cui viene inviato il messaggio. Ancora più sorprendente è il fatto che se non accade nulla nel thread, ad eccezione del fatto che il messaggio viene inviato al client, la risposta in realtà trova la sua strada verso il client.

Per riassumerlo: Se si verifica qualcosa di intensamente computazionale prima che il messaggio venga inviato, non viene consegnato, altrimenti lo è.

Come si dice here e here, l'invio di messaggi da un thread ai clienti non è affatto un problema:

In tutti gli esempi mostrato fino a questo punto il server risponde a un evento inviato dal cliente. Ma per alcune applicazioni, il server deve essere il mittente di un messaggio. Questo può essere utile per inviare notifiche ai client degli eventi originati nel server, ad esempio in un thread in background.

Ecco un esempio di codice. Quando rimuovi i commenti sharps (#) il messaggio ('pippo dal thread') non trova la sua strada verso il client, altrimenti lo fa.

from flask import Flask 
from flask.ext.socketio import SocketIO, emit 
app = Flask(__name__) 
socketio = SocketIO(app) 

from threading import Thread 
import time 

@socketio.on('client command') 
def response(data): 
    thread = Thread(target = testThreadFunction) 
    thread.daemon = True 
    thread.start() 

    emit('client response', ['foo']) 

def testThreadFunction(): 
# time.sleep(1) 

    socketio.emit('client response', ['foo from thread']) 

socketio.run(app) 

Sto usando Python 3.4.3, Flask 0.10.1, fiasco-socketio1.2, eventlet 0.17.4.

Questo esempio può essere copiato e incollato in un file .py e il comportamento può essere immediatamente riprodotto.

Qualcuno può spiegare questo strano comportamento?

Aggiornamento

sembra essere un bug di eventlet. Se lo faccio:

socketio = SocketIO(app, async_mode='threading') 

Forza l'applicazione a non utilizzare l'eventlet anche se è installato.

Tuttavia, questa non è una soluzione applicabile per me poiché si utilizza "threading" poiché async_mode rifiuta di accettare dati binari. Ogni volta che inviare alcuni dati binari dal client al server che dice:

WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.

La terza opzione, utilizzando gevent come l'async_mode non funziona per me così come gevent non ha il supporto per Python 3 ancora.

Quindi altri suggerimenti?

+0

@rfkortekaas come fa che hanno senso in un protocollo asincrono? E a parte questo la risposta viene inviata. Questo è ciò che "emette". L'altra cosa sta accadendo in un thread separato. – Schnodderbalken

+0

Ho rimosso il mio commento quando ho letto male la domanda. – rfkortekaas

+0

Mi sono imbattuto in un problema molto simile, ma non stavamo facendo nulla di computazionalmente costoso. Sembra essere un problema con l'acquisizione del corretto "socketio" quando si chiama socketio.emit. Perché l'emit si verifica, ma nessun client riceve il messaggio. L'aggiunta di async_mode = 'threading' sembrava risolvere il problema. Ma spero che ci sia un modo migliore – AMB0027

risposta

Problemi correlati