Установка переменной сеанса фляги вне контекста запроса (внутри генератора) - PullRequest
0 голосов
/ 04 июля 2018

У меня есть вид колбы, который выполняется для загрузки некоторой информации в генератор (я использую генератор, чтобы я мог непрерывно выводить прогресс - сколько информации загружено). Вот как выглядит вид:

@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

Я хотел бы сохранить информацию, которая загружается в переменную сеанса внутри генератора (эта функция генератора определена в другом файле вне контекста запроса). Но когда я пытаюсь получить доступ к переменной сеанса, я получаю следующую ошибку:

RuntimeError: Работа вне контекста запроса.

Итак, есть ли способ записать информацию в сессию таким образом? Я сейчас использую FileSystemSessionInterface, но готов использовать сеансы redis, если это решит мою проблему.

Обновление:

По предложению Sraw, я попробовал следующие изменения:

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

Но я все еще получаю ту же ошибку.

Обновление 2:

Итак, мне нужно использовать текущий экземпляр приложения вместо current_app (объект приложения создается в другом файле - app.py)

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

При этом я получаю ту же ошибку:

RuntimeError: Работа вне контекста запроса.

Обновление 3:

Ниже приведен код для 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"

1 Ответ

0 голосов
/ 05 июля 2018

В аналогичной настройке я получаю ту же ошибку, что и вы. Но используя:

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

решено. Так что в вашем случае это будет означать:

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:

Чисто технический подход с использованием функции обратного вызова, чтобы выполнить то, что вы хотите достичь. Если это это то, что вы хотите таким образом, это другой вопрос. Вы ввели 2 дополнительных параметра j и 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')
...