我正在使用https://github.com/miguelgrinberg/Flask- SocketIO来实现WebSocket服务器。
我需要从另一个进程(仅订阅)接收消息,并为特定房间中的客户端发出消息。
但是,当我尝试发送消息时,出现此错误:
无法将消息发送到家庭会议室:在请求上下文之外工作。
这是我的代码:
from flask import Flask, request from flask_socketio import SocketIO, join_room, leave_room, send, rooms import json import eventlet import logging import redis import threading FORMAT = '%(asctime)-15s - %(message)s' logging.basicConfig(format=FORMAT) log = logging.getLogger(__name__) app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app, async_mode='eventlet') . . . def _send_task_message(): try: send(json.dumps({"type":"UPDATE_TASK"}), room='home') except Exception as e: log.error('Could not send message to home room: %s' % str(e)) class Listener(threading.Thread): def __init__(self, r, channels): threading.Thread.__init__(self) self.daemon = True self.redis = r self.pubsub = self.redis.pubsub() self.pubsub.psubscribe(channels) def work(self, item): if isinstance(item['data'], bytes): try: msg = item['data'].decode('utf-8') decode_msg = json.loads(msg) if decode_msg['type'] == 'UPDATE_TASK': _send_task_message() except ValueError as e: log.error("Error decoding msg to microservice: %s", str(e)) def run(self): for item in self.pubsub.listen(): self.work(item) if __name__ == '__main__': r = redis.Redis() client = Listener(r, ['/bobguarana/socketio']) client.start() socketio.run(debug=True, app=app, port=8080)
我解决了将应用程序作为参数传递给类并按照错误描述的建议使用它的上下文,但是名称空间也是必需的:
class Listener(threading.Thread): def __init__(self, r, channels, app): threading.Thread.__init__(self) self.daemon = True self.redis = r self.pubsub = self.redis.pubsub() self.pubsub.psubscribe(channels) self.app = app def work(self, item): with app.app_context(): if isinstance(item['data'], bytes): try: msg = item['data'].decode('utf-8') decode_msg = json.loads(msg) if decode_msg['type'] == 'UPDATE_TASK': send(json.dumps({"type":"UPDATE_TASK"}), room='home', namespace='/') #_send_task_message() except ValueError as e: log.error("Error decoding msg to microservice: %s", str(e)) def run(self): for item in self.pubsub.listen(): self.work(item) if __name__ == '__main__': r = redis.Redis() client = Listener(r, ['/bobguarana/socketio'], app) client.start() socketio.run(debug=True, app=app, port=8080)