How to stop an infinite loop when you run Flask application in a production mode

Question:

I have the Flask application. It has two buttons Start and Stop. A program should print ‘pStart’ (an infinite loop of pStart-s) when a user click Start and stop printing when a user click Stop. A user can resume printing when he clicks Start the second time.

from flask import Flask, render_template
import sys
flag1=True
app = Flask(__name__)

@app.route('/')
def index():
  return render_template('index.html')

@app.route('/start/')
def start():
  globals()['flag1']=True
  while flag1==True:
    print('pStart')
  return render_template('index.html')

@app.route('/stop/')
def stop():
  globals()['flag1']=False
  return render_template('index.html')

if __name__ == '__main__':
  app.run(host='0.0.0.0')

Here is my templatesindex.html

<!doctype html>


<head>
    <title>Test</title> 
    <meta charset=utf-8>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

    </head>
    <body>
        <h1>My Website</h1>

<script type=text/javascript>
        $(function() {
          $('a#test').on('click', function(e) {
            e.preventDefault()
            $.getJSON('/start',
                function(data) {
              //do nothing
            });
            document.getElementById('btn1').disabled = true;
            document.getElementById('btn2').disabled = false;
            return false;
          });
        });
</script>

<script type=text/javascript>
        $(function() {
          $('a#test1').on('click', function(e) {
            e.preventDefault()
            $.getJSON('/stop',
                function(data) {
              //do nothing
            });
            document.getElementById('btn1').disabled = false;
            document.getElementById('btn2').disabled = true;
            return false;
          });
        });
</script>

<div class='container'>
        <form>
            <a href=# id=test><button id='btn1' class='btn btn-default'>Start</button></a>
        </form>
</div>  
<p>
<p>
<div class='container'>
        <form>
            <a href=# id=test1><button id='btn2' class='btn btn-default' type="button" disabled>Stop</button></a>
        </form>
</div>  
    </body>

This application works well in a development mode. However, when I run it with uWSGI I cannot stop it (stopless loop of print(‘pStart’)).
Here is my wsgi.py

from myproject import app

if __name__ == "__main__":
    app.run()

uwsgi –socket 0.0.0.0:5000 –protocol=http -w wsgi:app

Update. The Flask application works if to use threads in code and enable threads "uwsgi –socket 0.0.0.0:5000 –protocol=http –enable-threads -w wsgi:app"

Asked By: homievk

||

Answers:

The while loop in the start function runs indefinitely and can not handle incoming requests. So when you run the application in production mode, the server is not able to handle any incoming requests after the start function is called !

You can use a background task to run the print('pStart') continuously while allowing the Flask application to handle incoming requests, to do so use the threading modules.

Here’s how you can create the func in the background with threading :

  from flask import Flask, render_template
import threading
import time

app = Flask(__name__)
threads = []
stop_flags = []

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/start/')
def start():
    stop_flags.append(False)
    thread = threading.Thread(target=run_loop, args=(len(stop_flags) - 1,))
    threads.append(thread)
    thread.start()
    return render_template('index.html')

@app.route('/stop/')
def stop():
    stop_flags[-1] = True
    return render_template('index.html')

def run_loop(thread_id):
    while not stop_flags[thread_id]:
        print('pStart')
        time.sleep(1)

if __name__ == '__main__':
    app.run(debug=True)
Answered By: EL Amine Bechorfa
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.