あるスレッドでサーバーを起動し、別のスレッドで値プロデューサーを起動する必要があります (ここでは によって偽装されてmock_producer
います)。サーバーのバックグラウンド スレッドは、キューから各値を取得してクライアントに送信することになっています。同時に、WSGI サーバーはindex.html
、要求されたときにサービスを提供する必要があります。これまでで最高の試みは次のとおりです。
# pip install eventlet python-socketio
from threading import Thread
from Queue import Queue
import eventlet
import socketio
def mock_producer(queue):
import time
import itertools
for count in itertools.count():
queue.put(count)
time.sleep(5)
def background():
while True:
if not queue.empty():
value = queue.get()
sio.emit('value', value);
sio.sleep(0.1)
sio = socketio.Server(logger=True)
app = socketio.WSGIApp(sio, static_files={
'/': 'index.html',
})
queue = Queue()
prod_thread = Thread(target=mock_producer, args=(queue,))
prod_thread.start()
ws_server = eventlet.listen(('', 5000))
ws_thread = sio.start_background_task(background)
eventlet.wsgi.server(ws_server, app)
付属のおもちゃでindex.html
:
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.slim.js"></script>
<script>
const socket = io.connect();
socket.on('value', value => console.log(value));
</script>
</head>
<body></body>
</html>
私を悩ませているのはsio.sleep(0.1)
ラインです。これにより、オブジェクトがキューに入れられてから、オブジェクトがクライアントに提供されるまでの間に (わずかではありますが) 明らかに遅延が生じます。しかし、これはうまくいきません:
def background():
while True:
value = queue.get()
sio.emit('value', value);
その理由は、queue.get()
WSGIサーバーがページを提供できないブロックindex.html
です(これは明らかに同じスレッドで発生します)。
queue.get-emit ループの新しいスレッドを起動しようとしたとき (たとえば、Thread(target=background).start()
代わりに を使用sio.start_background_task(background)
)、デバッグ出力は、emit が発生していると主張していましたが、クライアントには何も到達していなかったため、これも失敗でした。
理想的には、リクエストを処理する必要があるか、キューに値が入るまでコードをアイドル状態にして、いずれかにすぐに反応するようにしたいと思います。
これをきれいに書く方法はありますか?
注意: 残念ながら、重大な依存関係があるため、このプロジェクトでは Python 2 のままです。唯一の結果はimport Queue from Queue
ラインだと思いますが、念のため。