20

I have been developing an app using Flask, Python and Flask-Socket.io library. The problem I have is that the following code will not perform an emit correctly due to some contexts issue

RuntimeError: working outside of request context

I am writing only one python file for the entire program by now. This is my code (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)

Here in StackExchange I have been reading some solutions, but they didn't work. I do not know what I am doing wrong.

I have tried adding a with app.app_context(): before my emit:

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

Another solution I tried is adding the decorator copy_current_request_context before someotherfunction() but it says that the decorator must be in a local scope. I put it in inside someotherfunction(), first line, but same error.

I would be glad if someone can help me with this. Thanks in advance.

doru
  • 9,022
  • 2
  • 33
  • 43
  • I'm not an expert in flask but I would think that `global someThread` on `setupconnect` is part of the problem. Also, maybe this thread can help you: http://stackoverflow.com/questions/9931738/flask-throwing-working-outside-of-request-context-when-starting-sub-thread – cnluzon Jul 27 '15 at 07:58

2 Answers2

21

Your error is 'working outside of request context'. You tried to resolve it by pushing the application context. Instead you should push the request context. See the explanation on contexts in flask on http://kronosapiens.github.io/blog/2014/08/14/understanding-contexts-in-flask.html

The code in your somefunction() probably uses objects (if i had to guess you probably use the request object) that are global inside the request context. Your code probably works when it is not executed inside the new thread. But when you execute it in a new thread your function is not executed in the original request context anymore and it does not have access to the request context specific objects anymore. So you have to push it manually.

so your function should be

def someotherfunction():
    with app.test_request_context('/'):
        emit('anEvent', jsondata, namespace='/test')
Mensur
  • 1,024
  • 15
  • 24
  • 13
    Thanks a lot! I tried but it gave me another error: `AttributeError: 'Request' object has no attribute 'namespace'`. I solved it executing `socketio.emit` instead of `emit`. `socketio` is the instantiated SocketIO object. – Sebasthian Ogalde Jul 27 '15 at 17:44
10

You are using the wrong emit here. You have to use the emit of the socketio object you created. so instead of

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

  • That doesn't work here, unfortunately. The message is never received by any of the clients. It appears to work when using `emit()` inside an actual `@sio.on()` handler (even using `sio.emit()` instead of `emit()`), but using `sio.emit()` from a different thread does nothing. – Niklas R Sep 08 '17 at 02:25
  • 1
    I just found out ([miguelgrinberg/python-socketio#16](https://github.com/miguelgrinberg/python-socketio/issues/16#issuecomment-271981963)) that I need to add `async_mode='threading'` to the construction of the `SocketIO` object. Then it works! – Niklas R Sep 08 '17 at 02:30
  • @NiklasR Did you do anything else as well? I am not receiving messages on client event after adding async_mode for creation of SocketIO. How did you start your server? – Vipul J Apr 06 '18 at 06:28