4

With threaded=True requests are each handled in a new thread. But if I set threaded true to my application it is showing unknown behavior.

This is my code.

from flask import Flask
from flask import jsonify
import time

app = Flask("proxapp")

import datetime

@app.route('/slow')
def slow():
    start = datetime.datetime.now()
    time.sleep(10)
    return jsonify(start = start, end = datetime.datetime.now())


try:
    app.run(threaded=True)
except Exception, e:
    print repr(e)

I have opened two tabs in windows and tried to request same url in different tabs. second request is being served only after first request is being served. Second request is taking ~20 seconds to be served.

What is the problem with my code?

Vishnu
  • 11,614
  • 6
  • 51
  • 90
  • 1
    I dunno what kind of threading Flask is using, but Python can only run _one_ native Python thread at a time. – ForceBru May 18 '17 at 17:12
  • 1
    As the default flask WSGI is only meant to be used for development anyways, I would suggest just switching to Gevent or gunicorn from the start, and would also fix the issue http://flask.pocoo.org/docs/0.12/deploying/wsgi-standalone/#standalone-wsgi-containers – CasualDemon May 18 '17 at 17:14
  • @ForceBru http://werkzeug.pocoo.org/docs/0.12/serving/#werkzeug.serving.run_simple – Vishnu May 18 '17 at 17:15
  • 2
    People coming in 2020 may notice that this snippet works perfectly, threaded, 2 threads in 10 secs. Just update old py2 prints and except declarations. – m3nda Dec 15 '20 at 17:28

4 Answers4

7

From the flask documentation about Deployment Options

While lightweight and easy to use, Flask’s built-in server is not suitable for production as it doesn’t scale well and by default serves only one request at a time. Some of the options available for properly running Flask in production are documented here.

That's why your second request isn't happening until the first is complete, because the flask server on it's own can only handle one request at a time. To solve this you will need to run Flask on some kind of deployment server for example gunicorn or uWSGI which seem to be the most popular.

You also might find the answer to this or this question helpful. Deployment Options also has a lot of links to guides and information about different ways of solving your issue.

Community
  • 1
  • 1
Kai
  • 1,709
  • 1
  • 23
  • 36
  • 13
    The text you quote says: "by default serves only one request at a time". The OP is overriding the default behavior, by specifying `threaded=True`. – dcatteeu Feb 06 '18 at 07:25
5

I cant seem to find my reference but I recall reading from another SO post why two tabs from the same browser fail when requesting form the same route despite threaded=True.

The gist of the post was that while threading will handle multiple connections to the same app better, the browser itself will try to reuse any already open connections. So with your two tab setup you could request from different routes and it work fine but if you request from the same route youll run into an issue because of the recycling of connections by the browser. Try opening two different browsers and testing this. Again I apologize for not having my original reference, I would like to give the author credit. If I find it Ill update this post.

BejanSadeghian
  • 609
  • 1
  • 6
  • 10
0

I found the most tricky problem! No matter what dubug server or production wsgi server you are using! When you are trying multi processes or multi threads! You should use different browsers or Chrome incognito window!!!!

solve all my problem! sample code here

from flask import Flask
import time
import os
import threading as td

app = Flask(__name__)

#trying  http://127.0.0.1:5000/
@app.route('/')
def index():
    print('index')
    print('pid:', os.getpid())
    print('thread id:', td.get_ident())
    time.sleep(10)
    return "Hello, World!"


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, threaded=True)
Wess Wang
  • 61
  • 1
  • 7
  • 1
    thanks! that is exactly what was happening to me... I was so confused beforehand, for hours. – nmz787 Jul 18 '22 at 21:33
-1

Python's GIL allows only 1 thread to run at a time. So 2 requests will take 20 seconds in total. Whether they will run one at a time or interleave each other depends on many things, including the OS.

dcatteeu
  • 481
  • 3
  • 10