Flask,Python和Socket.io:多线程应用程序给我"RuntimeError:在请求上下文之外工作"

Seb*_*lde 12 python sockets multithreading flask socket.io

我一直在使用Flask,PythonFlask-Socket.io库开发应用程序.我emit遇到的问题是由于某些上下文问题,以下代码将无法正确执行

RuntimeError: working outside of request context
Run Code Online (Sandbox Code Playgroud)

我现在只为整个程序编写一个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)
Run Code Online (Sandbox Code Playgroud)

在StackExchange中,我一直在阅读一些解决方案,但它们没有用.我不知道我做错了什么.

我试过with app.app_context():在我之前添加一个emit:

def someotherfunction():
    # some other tasks
    with app.app_context():
        emit('anEvent', jsondata, namespace='/test') # same error here
Run Code Online (Sandbox Code Playgroud)

我尝试的另一个解决方案是添加装饰器copy_current_request_context,someotherfunction()但它说装饰器必须在本地范围内.我把它放在里面someotherfunction(),第一行,但同样的错误.

如果有人可以帮助我,我会很高兴.提前致谢.

Men*_*sur 14

您的错误是"在请求上下文之外工作".您试图通过推送应用程序上下文来解决它.相反,您应该推送请求上下文.请参阅http://kronosapiens.github.io/blog/2014/08/14/understanding-contexts-in-flask.html上关于烧瓶中背景的说明

somefunction()中的代码可能使用请求上下文中全局的对象(如果我不得不猜测你可能使用请求对象).您的代码可能在新线程内未执行时有效.但是当您在新线程中执行它时,您的函数不再在原始请求上下文中执行,并且它不再能够访问请求上下文特定对象.所以你必须手动推送它.

所以你的功能应该是

def someotherfunction():
    with app.test_request_context('/'):
        emit('anEvent', jsondata, namespace='/test')
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢!我尝试了但它给了我另一个错误:`AttributeError:'Request'对象没有属性'namespace'.我解决了它执行`socketio.emit`而不是`emit`.`socketio`是实例化的SocketIO对象. (5认同)
  • 别客气.很高兴现在有效. (3认同)

小智 8

你在emit这里用错了。您必须使用您创建的 socketio 对象的发射。所以而不是

emit('anEvent', jsondata, namespace='/test') # here occurs the error 用: socketio.emit('anEvent', jsondata, namespace='/test') # here occurs the error