252

I know I can link Flask with Apache or other web servers. But, I was thinking of running Flask as a standalone server serving multiple clients simultaneously.

Is this possible? Do I have to handle spawning multiple threads and managing them?

ATOzTOA
  • 34,814
  • 22
  • 96
  • 117

3 Answers3

361

flask.Flask.run accepts additional keyword arguments (**options) that it forwards to werkzeug.serving.run_simple - two of those arguments are threaded (a boolean) and processes (which you can set to a number greater than one to have werkzeug spawn more than one process to handle requests).

threaded defaults to True as of Flask 1.0, so for the latest versions of Flask, the default development server will be able to serve multiple clients simultaneously by default. For older versions of Flask, you can explicitly pass threaded=True to enable this behaviour.

For example, you can do

if __name__ == '__main__':
    app.run(threaded=True)

to handle multiple clients using threads in a way compatible with old Flask versions, or

if __name__ == '__main__':
    app.run(threaded=False, processes=3)

to tell Werkzeug to spawn three processes to handle incoming requests, or just

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

to handle multiple clients using threads if you know that you will be using Flask 1.0 or later.

That being said, Werkzeug's serving.run_simple wraps the standard library's wsgiref package - and that package contains a reference implementation of WSGI, not a production-ready web server. If you are going to use Flask in production (assuming that "production" is not a low-traffic internal application with no more than 10 concurrent users) make sure to stand it up behind a real web server (see the section of Flask's docs entitled Deployment Options for some suggested methods).

HackDolphin
  • 166
  • 11
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • 2
    What if I am looking at a max of 100 users? Can I just assign `processes=100` and be happy with it? In my case, I only need static files, no HTTP Post methods. My requirement is, I want to run all Flask threads as part of my parent app, so that they all can share variables. – ATOzTOA Feb 12 '13 at 06:03
  • 6
    *Chuckles* - @ATOzTOA - no, that would probably be *quite* counter-productive (Processes are relatively expensive, and unless you are doing a lot of work in each request there is no reason why 4 or 8 processes shouldn't be enough). That said, if you are only displaying static content you would be better off with a server that is optimized for doing that (Apache, ngnix, IIS). – Sean Vieira Feb 12 '13 at 11:11
  • 3
    Also, you shouldn't commonly need to share variables across requests - if you *do* you'll either need to limit yourself to one process or use some out-of-band communication (Redis, a database, the filesystem, etc.) so that each of your processes stays synced. – Sean Vieira Feb 12 '13 at 11:13
  • Yeah right. So, if I set `processes=4`, then it should spawn 100 threads as per my need, won't it? – ATOzTOA Feb 12 '13 at 11:24
  • 1
    @ATOzTOA - are you planning on having 100 *concurrent* users or 100 users *total*? It most likely will not spawn 100 threads, it will spawn some lower number and handle the connections as they come in - you don't need a 1 to 1 match between incoming connections and handlers - but as the number of *concurrent* incoming connections goes up you either need to increase the number of handlers (which is counter-productive after a certain number) or decrease your handling time. If you are planning on 100 concurrent users you'll probably want a vetted webserver, rather than wsgiref. – Sean Vieira Feb 12 '13 at 12:46
  • OK, so if I will only ever have 100 users *total*, then can I just have Flask without any other components? – ATOzTOA Feb 12 '13 at 13:21
  • 3
    @ATOzTOA - if you can't spin up a better server then I'd just give it a whirl and see what happens. If it doesn't perform well under load you can deploy it behind a different webserver. – Sean Vieira Feb 12 '13 at 14:20
  • 2
    @ATOzTOA, regarding your question about why you can't specify 'threaded' and 'processes' at the same time, cf the code here: http://werkzeug.readthedocs.org/en/latest/_modules/werkzeug/serving/ – pyrho Aug 29 '14 at 09:37
  • Does using N `processes` run N concurrent applications? If I use globals to be shared by different views within the app, they only share properly if processes is 1. I expect each of the N processes to have its own copy of the globals to share among its views, but not between the processes. Even globals within a process are unusable if `processes>1`. Will `flask.g` properly share globals if `multithreaed=True` or `processes=N` for `N>1`? – hamx0r Feb 11 '16 at 04:22
  • Is it possible to specify `processes=N` when running a Flask app as a package form the command line? – RagingRoosevelt May 02 '18 at 15:36
  • Not when last I checked @RagingRoosevelt - but that may have changed. – Sean Vieira May 05 '18 at 14:28
  • For the ones who is looking to know how is the full solution using Docker, can see [this](http://docker.lhsm.com.br/b1c2913d-f33d-43c7-b519-b016940d1d24) post. –  Jan 04 '19 at 12:27
71

Using the simple app.run() from within Flask creates a single synchronous server on a single thread capable of serving only one client at a time. It is intended for use in controlled environments with low demand (i.e. development, debugging) for exactly this reason.

Spawning threads and managing them yourself is probably not going to get you very far either, because of the Python GIL.

That said, you do still have some good options. Gunicorn is a solid, easy-to-use WSGI server that will let you spawn multiple workers (separate processes, so no GIL worries), and even comes with asynchronous workers that will speed up your app (and make it more secure) with little to no work on your part (especially with Flask).

Still, even Gunicorn should probably not be directly publicly exposed. In production, it should be used behind a more robust HTTP server; nginx tends to go well with Gunicorn and Flask.

Ryan Artecona
  • 5,953
  • 3
  • 19
  • 18
  • 21
    not quite. Gunicorn is python, nginx is not. that's not how you would use them, though. Gunicorn would let you run your app as `gunicorn app:app 127.0.0.1:8080` instead of `python app.py`. Nginx would act as the public service that exposes your private Gunicorn-run app [(a reverse-proxy)](http://en.wikipedia.org/wiki/Reverse_proxy), hiding all sorts of lower level HTTP implementation details, perhaps serving static files directly, etc. – Ryan Artecona Feb 11 '13 at 16:56
  • 1
    Flask with app.run(threaded=True) runs very nice on Apache2 using mod_wsgi https://flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi/ – MortenB Feb 29 '20 at 21:06
  • Where does Apache fit in this picture? I have shared hosting where I must use it. I'm recreating the environment on a VPS to get the hands on. Thanks – John Oct 19 '20 at 06:30
22

Tips from 2020:

From Flask 1.0, it defaults to enable multiple threads (source), you don't need to do anything, just upgrade it with:

$ pip install -U flask

If you are using flask run instead of app.run() with older versions, you can control the threaded behavior with a command option (--with-threads/--without-threads):

$ flask run --with-threads

It's same as app.run(threaded=True)

Grey Li
  • 11,664
  • 4
  • 54
  • 64