【问题标题】:Flask, Python and Socket.io: multithreading app is giving me "RuntimeError: working outside of request context"Flask、Python 和 Socket.io:多线程应用程序给了我“RuntimeError:在请求上下文之外工作”
【发布时间】:2015-10-17 06:48:41
【问题描述】:

我一直在使用 FlaskPythonFlask-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() 里面,第一行,但同样的错误。

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

【问题讨论】:

标签: python multithreading sockets flask socket.io


【解决方案1】:

您的错误是“在请求上下文之外工作”。您试图通过推送应用程序上下文来解决它。相反,您应该推送请求上下文。请参阅 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')

【讨论】:

  • 非常感谢!我试过了,但它给了我另一个错误:AttributeError: 'Request' object has no attribute 'namespace'。我解决了它执行socketio.emit 而不是emitsocketio 是实例化的 SocketIO 对象。
【解决方案2】:

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

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

【讨论】:

  • 不幸的是,这在这里不起作用。任何客户端都不会收到该消息。在实际的@sio.on() 处理程序中使用emit() 时,它似乎可以工作(即使使用sio.emit() 而不是emit()),但在不同的线程中使用sio.emit() 没有任何作用。
  • 我刚刚发现 (miguelgrinberg/python-socketio#16) 我需要将 async_mode='threading' 添加到 SocketIO 对象的构造中。然后就可以了!
  • @NiklasR 你还做了其他事情吗?添加 async_mode 以创建 SocketIO 后,我没有收到有关客户端事件的消息。您是如何启动服务器的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 2021-09-17
  • 2023-02-03
  • 2015-10-05
相关资源
最近更新 更多