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)