7

I have a flask view which is executed to load some information in a generator (I am using a generator so that I can continuously yield the progress - how much information has loaded). Here is what the view looks like:

@app.route("/progress", methods=['GET'])
def progress():
     gen = get_user_saved_tracks(session['token'], session['spotify_id'], session)
     return Response(gen, mimetype= 'text/event-stream')

def get_user_saved_tracks(token, id, session):
    #load information and keep yielding
    session['info'] = info

I would like to store the information which is loaded in a session variable inside the generator (This generator function is defined in a different file, outside the request context). But when I try to access the session variable, I get the following error:

RuntimeError: Working outside of request context.

So, is there a way to write the information to the session in this way? I am using FileSystemSessionInterface right now but willing to use redis sessions if that will solve my issue.

Update:

As suggested by Sraw, I tried the following changes:

from flask import current_app
app = current_app._get_current_object()
def get_user_saved_tracks(token, id,session):
    with app.app_context():
        session['info'] = info

But I still get the same error.

Update 2:

So, I need to use the actual app instance instead of using current_app (app object is being created in a different file - app.py)

from app import app
def get_user_saved_tracks(token, id,session):
    with app.app_context():
        session['info'] = info

On doing this, I get the same error:

RuntimeError: Working outside of request context.

Update 3:

Following is the code for get_user_saved_tracks:

def get_user_saved_tracks(token, id, session, j, service):
    tracks = []
    for i in range(100):
        a = service.current_user_saved_tracks(limit=50, offset=i*50)
        if len(a['items']) == 0:
            break
        yield "data:" + "lib" + str((float(i+1)/(j))*100) + "\n\n"
        time.sleep(0.5)
        tracks.extend(a)

    session['tracks'] = tracks
    session.modified = True
    yield "data:" + "close" + "\n\n"
8
  • stackoverflow.com/a/34123343/5588279 Commented Jul 4, 2018 at 9:56
  • @Sraw : Thanks! Added update to the question. Commented Jul 5, 2018 at 10:02
  • Not, you cannot use current_app in this way. You should directly use the app instance. I mean, the app reference created by Flask(__name__, xxxx). Commented Jul 5, 2018 at 10:04
  • @Sraw Thanks! Added another update. Commented Jul 5, 2018 at 10:14
  • I think we need more information to help you. It seems you are not running that code during handling a request. Commented Jul 5, 2018 at 10:18

2 Answers 2

0

In similar setup I get the same error as you do. But by using:

return Response(stream_with_context(....),
                mimetype='text/event-stream')

it is resolved. So in your case that would mean:

from flask import Flask, stream_with_context, request, Response, session
....

return Response(stream_with_context(get_user_saved_tracks(session['token'], session['spotify_id'], session),
                mimetype='text/event-stream')

EDIT:

A pure technical approach by using a callback function to get done what you want to accomplish. If this is something you want this way is a different question. You introduced 2 additional parameters j and service (?).

def get_user_saved_tracks(cb, token, id, j, service):
    #tracks = []
    for i in range(100):
        a = service.current_user_saved_tracks(limit=50, offset=i*50)
        if len(a['items']) == 0:
            break
        yield "data:" + "lib" + str((float(i+1)/(j))*100) + "\n\n"
        time.sleep(0.5)
        #tracks.extend(a)
        cb(a)  # <<--------

    #self.session['tracks'] = tracks
    #self.session.modified = True
    yield "data:" + "close" + "\n\n"

@app.route("/progress", methods=['GET'])
def progress():
    # add a callback function to update the session for the 'a' you
    # calculate in get_user_saved_tracks(). The callback updates the session
    session['tracks'] = []
    def cb(l):
        session['tracks'].extend(l)
    session.modied = True

    return Response(stream_with_context(get_user_saved_tracks(cb, session['token'], session['spotify_id']),  # j and service ?
            mimetype='text/event-stream')
Sign up to request clarification or add additional context in comments.

4 Comments

Hi! Yes, the error is resolved. However, writing to session variable in get_user_saved_tracks still doesn't work (the written information is not available in the next request), even after doing session.modified=True
you should post the code of get_user_saved_tracks(...)
Just to be sure: does you session mechanism work OK ? simply storing somehing like session['name'] = "Santa" and getting it from another url by: session.get('name') works OK?
0

I just solved our problem. Call this to save session anywhere.

def _session_save():
    from flask.globals import _request_ctx_stack
    app.session_interface.save_session(app, _request_ctx_stack.top.session, flask.Response())

I haven't checked it properly yet, so the final solution might look like this:

def _session_save(session):  # pass flask.session from context
    app.session_interface.save_session(app, session, flask.Response())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.