4

I am in process of building a small utility using Flask and python(ver 3.6).

This utility is basically calling external systems (sys1 and sys2) using REST calls and synching data unidirectionally from sys1 to sys2. This synch process will run continuously till a kill flag is set.

I want the ability to start and stop this synch process/method using flask routes.

for example,

  • if a request is received at /start,
    o Then start then start this method.
    o return a HTTP response code (the response should not wait for method to complete)

  • if a request is received at /stop, o if the method is running, stop the method by setting kill flag. (here again, the response from flask should not wait for method to complete)

Now,I went though many of the queries here and other sites but they all seem to cater to specific needs. Based on my understanding, I have tried the following things (may be improperly to achieve this task:

  1. Tried creating a thread from the route and call the method - Didn't work as for some reason flask waited for the method to complete (is it because flask is single threaded and blocking ?)

  2. Read up on celery but i feel it may be an overkill to use celery in this case.

What would be a correct way to start this process asynchronously & how? Threads ? asyncio or Celery is the only way.

k_r
  • 73
  • 1
  • 6
  • You might have to set flask to use threads, take a look [here](https://stackoverflow.com/a/14823968/1177119). Another option could be to use process interop you could launch a subprocess using python's subprocess module and catch a signal to kill the process. – Josh Voigts Apr 13 '18 at 16:52

1 Answers1

5

Here is a working example. When you call run it will start a 1 second loop that prints "running...". Then when you call stop it modifies a global variable that the threaded function checks for the loop and stops.

You should be able to paste and go, then just modify for your purposes from there.

from flask import Flask, Response
from threading import Thread
from time import sleep

app = Flask(__name__)

stop_run = False


def my_function():
    global stop_run
    while not stop_run:
        sleep(1)
        print("running...")


def manual_run():
    t = Thread(target=my_function)
    t.start()
    return "Processing"


@app.route("/stop", methods=['GET'])
def set_stop_run():
    global stop_run
    stop_run = True
    return "Application stopped"


@app.route("/run", methods=['GET'])
def run_process():
    global stop_run
    stop_run = False
    return Response(manual_run(), mimetype="text/html")


if __name__ == "__main__":
    app.run()
Chris Farr
  • 3,580
  • 1
  • 21
  • 24
  • thanks. That's very helpful. The only thing is that with global variable it didn't work for me. What I ended up with was creating file status.txt and at the beginning of while loop I always use open to check if status has changed. And on stop endpoint I rewrite this file with corresponding word "stop" so that while loop will stop – president Jan 03 '20 at 13:33
  • You probably can use an environment variable and set it as active/inactive instead of a text file. just `import os; os.environ['running_flag'] = 'running'`. – Masoud Masoumi Moghadam May 13 '20 at 08:53