In my old post, I have shared how to run the builtin development server to serve the web API. For production, we need to use more powerful web servers. Flask complies to the WSGI (Web Server Gateway Interface) specification and can work with any web server that conforms to WSGI.
In this post, I want share how to run Flask applications using uWSGI — a popular WSGI-compliant server.
Install and simple running
To install uWSGI, we can use pip:
pip install uwsgi
To run a simple flask application using uWSGI, we can use the following commands:
uwsgi --http 0.0.0.0:8081 --module flask-app:app --master --processes 2 --threads 2 # or run following command # uwsgi --socket 0.0.0.0:8081 --protocol=http --module flask-app:app
Run uWSGI via config
When we use more options via the command line, it becomes less convenient. We
can also use an
ini file to config uWSGI like this:
[uwsgi] chdir=/path/to/project wsgi-file=flask-demo.py callable=app http=0.0.0.0:1234 need-app=true lazy-apps=true master=true processes=2 threads=2 single-interpreter=true die-on-term=true procname-prefix-spaced=flask demo vacuum=true pidfile=demo.pid
Save this file as
uwsgi.ini (or whatever you like), and then run the
uwsgi --ini uwsgi.ini. If the extention of config file is
ini, we also directly run uWSGI as this:
Below are the meanings of some of these options:
chdir option specifies the directory to run the application.
wsgi-file and callable
wsgi-file specify the source file where your application resides.
are the name of your application. For example, if you define your application
app = Flask(__name__), then you should set
callable = app.
With master mode on, the master process will restart a worker process if it
dies. Generally, it is good idea to turn master mode on with
master = true.
By default, uwsgi will enable multiple interpreter mode, i.e., running multiple apps in a single process using different interpreter. If we are running a single app, it is not necessary to run in this mode.
die-on-term = true, you can not kill uwsgi process via
Instead, uWSGI will reload a process if it were killed. This may not be what
need-app = true, uWSGI will not run if it can not find the application to
run. Otherwise, it will load even without an application. When you request the
service, you will get HTTP 500 responses.
lazy-apps=true, each process will initialize applications indepently of
each other. If you do not set this option, you may run into troubles. For
example, someone reported that PyTorch model are not runnning properly using
uWSGI and flask if
lazy-apps option is not
See also official discussion here.
It will add a custom prefix to uwsgi process so that you can find the process for a specific application easily.
proc-name-spaced = demo
will produce the following output:
jdhao 29516 1.0 0.0 110104 14852 pts/31 S+ 21:16 0:00 demo uWSGI master jdhao 29520 5.5 0.0 186184 28080 pts/31 S+ 21:16 0:00 demo uWSGI worker 1 jdhao 29521 0.0 0.0 110104 7644 pts/31 S+ 21:16 0:00 demo uWSGI http 1
py-autoreload=2 will check if file is modified every 2 seconds and restart
application if modification detected. This should only be used for debugging,
and not for production.
pidfile will create a file under specified location with the pid of
uWSGI master process. To kill the uWSGI process safely, you can use the following
uwsgi --stop demo.pid
When I try to kill the uwsgi process via
Ctrl-C, I found that uwsgi takes
long time to stop and print the following message when it finally stops:
worker 1 buried after 30 seconds goodbye to uWSGI. VACUUM: pidfile removed.
To close the uwsgi process quicker, we can add the
and set it to a small value:
# set it to 5 seconds worker-reload-mercy = 5
It set the number of seconds uWSGI will wait for the worker to exit before killing it brutally.
Then when you start uwsgi, you will see the following log message:
your mercy for graceful operations on workers is 5 seconds
License CC BY-NC-ND 4.0