我一直在开发一个应用程序使用Flask, Python和Flask- socket。io 图书馆。我遇到的问题是,由于一些上下文问题,以下代码将无法正确执行emit
RuntimeError: working outside of request context
我现在只为整个程序编写一个python文件。这是我的代码(test.py):
from threading import Thread
from flask import Flask, render_template, session, request, jsonify, current_app, copy_current_request_context
from flask.ext.socketio import *
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
def somefunction():
# some tasks
someotherfunction()
def someotherfunction():
# some other tasks
emit('anEvent', jsondata, namespace='/test') # here occurs the error
@socketio.on('connect', namespace='/test')
def setupconnect():
global someThread
someThread = Thread(target=somefunction)
someThread.daemon = True
if __name__ == '__main__':
socketio.run(app)
这里在StackExchange我一直在阅读一些解决方案,但他们没有工作。我不知道我做错了什么。
我尝试在emit
之前添加with app.app_context():
:
def someotherfunction():
# some other tasks
with app.app_context():
emit('anEvent', jsondata, namespace='/test') # same error here
我尝试的另一个解决方案是在someotherfunction()
之前添加装饰器copy_current_request_context
,但它说装饰器必须在本地范围内。我把它放在someotherfunction()
,第一行,但同样的错误。
您的错误是"在请求上下文之外工作"。您试图通过推送应用程序上下文来解决这个问题。相反,您应该推送请求上下文。参见http://kronosapiens.github.io/blog/2014/08/14/understanding-contexts-in-flask.html
对flask中上下文的解释。代码在你的somefunction()可能使用对象(如果我不得不猜测你可能使用请求对象)是全局的请求上下文中。您的代码在没有在新线程内执行时可能会正常工作。但是当你在一个新线程中执行它时,你的函数不再在原始请求上下文中执行,并且它不再具有访问请求上下文特定对象的权限。所以你必须手动推它。
所以你的函数应该是def someotherfunction():
with app.test_request_context('/'):
emit('anEvent', jsondata, namespace='/test')
您在这里使用了错误的emit
。您必须使用您创建的套接字对象的emit。所以不用
emit('anEvent', jsondata, namespace='/test') # here occurs the error
使用:
socketio.emit('anEvent', jsondata, namespace='/test') # here occurs the error