Skip to content
Advertisement

How to let a Flask web page (route) run in the background while on another web page(route)

So i’m creating this application and a part of it is a web page where a trading algorithm is testing itself using live data. All that is working but the issue is if i leave (exit) the web page, it stops. I was wondering how i can keep it running in the background indefinitely as i want the algorithm to keep doing it’s thing.

This is the route which i would like to run in the background.

@app.route('/live-data-source')
def live_data_source():
    def get_live_data():
        live_options = lo.Options()
        while True:
            live_options.run()
            live_options.update_strategy()
            trades = live_options.get_all_option_trades()
            trades = trades[0]
            json_data = json.dumps(
                {'data': trades})
            yield f"data:{json_data}nn"
            time.sleep(5)

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

I’ve looked into multi-threading but not too sure if that’s the right thing for the job. I am kind of still new to flask so hence the poor question. If you need more info, please do comment.

Advertisement

Answer

You can do it the following way – this is 100% working example below. Note, in production use Celery for such tasks, or write another one daemon app (another process) by yourself and feed it with tasks from http server with the help of message queue (e.g. RabbitMQ) or with the help of common database.

If any questions regarding code below, feel free to ask, it was quite good exercise for me:

from flask import Flask, current_app
import threading
from threading import Thread, Event
import time
from random import randint

app = Flask(__name__)
# use the dict to store events to stop other treads
# one event per thread !
app.config["ThreadWorkerActive"] = dict()


def do_work(e: Event):
    """function just for another one thread to do some work"""
    while True:
        if e.is_set():
            break  # can be stopped from another trhead
        print(f"{threading.current_thread().getName()} working now ...")
        time.sleep(2)
    print(f"{threading.current_thread().getName()} was stoped ...")


@app.route("/long_thread", methods=["GET"])
def long_thread_task():
    """Allows to start a new thread"""
    th_name = f"Th-{randint(100000, 999999)}"  # not really unique actually
    stop_event = Event()  # is used to stop another thread
    th = Thread(target=do_work, args=(stop_event, ), name=th_name, daemon=True)
    th.start()
    current_app.config["ThreadWorkerActive"][th_name] = stop_event
    return f"{th_name} was created!"


@app.route("/stop_thread/<th_id>", methods=["GET"])
def stop_thread_task(th_id):
    th_name = f"Th-{th_id}"
    if th_name in current_app.config["ThreadWorkerActive"].keys():
        e = current_app.config["ThreadWorkerActive"].get(th_name)
        if e:
            e.set()
            current_app.config["ThreadWorkerActive"].pop(th_name)
            return f"Th-{th_id} was asked to stop"
        else:
            return "Sorry something went wrong..."
    else:
        return f"Th-{th_id} not found"


@app.route("/", methods=["GET"])
def index_route():
    text = ("/long_thread - create another thread.  "
            "/stop_thread/th_id - stop thread with a certain id.  "
            f"Available Threads: {'; '.join(current_app.config['ThreadWorkerActive'].keys())}")
    return text


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=9999)
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement