问题
I am creating a live reporting application using Flask, Flask-Socketio and Flask-SQLAlchemy. My current design creates a background thread on connection which querys an API and inserts into the applications data. However, when running this, I get the error
RuntimeError: No application found. Either work inside a view function or push an application context.
flask_react_app.py:
from threading import Lock
from flask import Blueprint, render_template
from .model import Stock
from . import socketio
main = Blueprint('main', __name__)
thread_lock = Lock()
thread = None
@main.route('/')
def index():
"""Serve client-side application."""
return render_template('index.html', async_mode=socketio.async_mode)
def generate_data():
"""
returns the Stock object query set
"""
return [i.serialize for i in Stock.query.all()]
def background_thread():
"""Example of how to send server generated events to clients."""
while True:
socketio.sleep(10)
socketio.emit("my_response", generate_data())
@socketio.on("connect")
def test_connect():
"""
Connect method which fires off thread to notify worker to get data.
:return: emits initial data.
"""
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(target=background_thread)
socketio.emit("my_response", generate_data())
I have two issues with this. Firstly the bug mentioned, secondly, there must be a better way!
回答1:
Your problem is not related to Flask-SocketIO, but to the fact that to use Flask-SQLAlchemy in a background thread you need an application context for it.
Try the following:
def background_thread(app):
"""Example of how to send server generated events to clients."""
with app.app_context():
while True:
socketio.sleep(10)
socketio.emit("my_response", generate_data())
Then in the place where you start the background thread pass the application instance as an argument:
thread = socketio.start_background_task(target=background_thread, args=(current_app._get_current_object(),))
回答2:
Miguel's answer is right but if both keywords arguments are passed to the function, then the next exception is raised:
TypeError: background_thread() got an unexpected keyword argument 'args'
So you have to pass only
thread = socketio.start_background_task(background_thread, (current_app._get_current_object()))
来源:https://stackoverflow.com/questions/49252601/flask-socketio-context-for-flask-sqlalchemy