Flask:无法从 socket.io 监听器中访问 current_app
Posted
技术标签:
【中文标题】Flask:无法从 socket.io 监听器中访问 current_app【英文标题】:Flask: Unable to access current_app from within socket.io listener 【发布时间】:2013-03-24 12:13:20 【问题描述】:我正在尝试从侦听器中访问 current_app,以便我可以使用应用配置值来订阅哪个频道。但是我收到“RuntimeError:在应用程序上下文之外工作”。
这里是有问题的代码:
from flask import Blueprint, Response, request, current_app
from socketio import socketio_manage
from socketio.namespace import BaseNamespace
from redis import StrictRedis
import pprint
socketapp = Blueprint('socketapp', __name__)
class MessageNamespace(BaseNamespace):
def listener(self):
pprint.pprint(current_app.config)
r = StrictRedis()
p = r.pubsub()
p.subscribe('message-channel')
messages = r.lrange('message', 0, -1)
self.emit('message-message', ''.join(messages))
for m in p.listen():
if m['type'] == 'message':
self.emit('message-message', m['data'])
def on_subscribe(self):
self.spawn(self.listener)
@socketapp.route('/socket.io/<path:remaining>')
def socketio(remaining):
try:
socketio_manage(request.environ, '/messages': MessageNamespace, request)
except BaseException:
pass
return Response()
@socketapp.route('/message', methods=['GET'])
def say():
msg = request.args.get('msg', None)
if msg:
r = StrictRedis(host=current_app.config['REDIS_HOST'])
r.rpush('message', msg)
r.publish('message-channel', msg)
return Response('Message sent!')
else:
return Response('Please specify your message in the "msg" parameter')
【问题讨论】:
你见过这个sn-p - flask.pocoo.org/snippets/105 @SeanVieira,您的 sn-p 在命名空间构造函数中使用 current_app,但它不可用。我根据您的代码编写了我的 hack 版本。请查看。 【参考方案1】:current_app
仅在处理 HTTP 请求时有效(它是暂时指向实际应用程序对象的代理)。您需要从此模块访问实际的应用程序对象,或者通过current_app._get_current_object()
窃取对它的引用。
【讨论】:
【参考方案2】:Sean 的 sn-p 对我不起作用。我基于它编写了以下 hack:
@bp.route('/<path:remaining>')
def socketio(remaining):
app = current_app._get_current_object()
try:
# Hack: set app instead of request to make it available in the namespace.
socketio_manage(request.environ, '': ChatNamespace, app)
except:
app.logger.error("Exception while handling socket.io connection", exc_info=True)
return Response()
class ChatNamespace(BaseNamespace, RoomsMixin, BroadcastMixin):
def __init__(self, environ, ns_name, request=None):
self.context = None
if request:
# Hack: initialize context with app that was set instead of request. Then miss it in parent constructor call.
app = request
self.context = app.request_context(environ)
self.context.push()
app.preprocess_request()
super(ChatNamespace, self).__init__(environ, ns_name)
def log(self, message):
# Now we can access app and other goodies.
self.context.app.logger.info("[0] 1".format(self.socket.sessid, message))
def disconnect(self, *args, **kwargs):
if self.context:
self.context.pop()
super(ChatNamespace, self).disconnect(*args, **kwargs)
【讨论】:
以上是关于Flask:无法从 socket.io 监听器中访问 current_app的主要内容,如果未能解决你的问题,请参考以下文章