WSGI Servers

Why is WSGI necessary?

A traditional web server does not understand or have any way to run Python
applications. In the late 1990s, a developer named Grisha Trubetskoy
came up with an Apache module called mod_python
to execute arbitrary Python code. For several years in the late 1990s
and early 2000s, Apache configured with mod_python ran most Python web
applications.

However, mod_python wasn't a standard specification. It was just an
implementation that allowed Python code to run on a server. As mod_python's
development stalled and security vulnerabilities were discovered there
was recognition by the community that a consistent way to execute Python
code for web applications was needed.

Therefore the Python community came up with WSGI as a standard interface that
modules and containers could implement. WSGI is now the accepted approach
for running Python web applications.

As shown in the above diagram, a WSGI server simply invokes a callable object
on the WSGI application as defined by the PEP 3333 standard.

WSGI's Purpose

Why use WSGI and not just point a web server directly at an application?

WSGI gives you flexibility. Application developers can swap out
web stack components for others. For example, a developer can switch from
Green Unicorn to uWSGI without modifying the application or framework
that implements WSGI.
From PEP 3333:

The availability and widespread use of such an API in web servers for
Python [...] would separate choice of framework from choice of web
server, freeing users to choose a pairing that suits them, while
freeing framework and server developers to focus on their preferred
area of specialization.

WSGI servers promote scaling. Serving thousands of requests for dynamic
content at once is the domain of WSGI servers, not frameworks.
WSGI servers handle processing requests from the web server and deciding
how to communicate those requests to an application framework's process.
The segregation of responsibilities is important for efficiently scaling
web traffic.

WSGI is by design a simple standard interface for running Python code. As
a web developer you won't need to know much more than

what WSGI stands for (Web Server Gateway Inteface)

that a WSGI container is a separate running process that runs on a
different port than your web server

your web server is configured to pass requests to the WSGI container which
runs your web application, then pass the response (in the form of HTML)
back to the requester

If you're using a standard web framework such as Django, Flask, or
Bottle, or almost any other current Python framework, you don't need to worry
about how frameworks implement the application side of the WSGI standard.
Likewise, if you're using a standard WSGI container such as Green Unicorn,
uWSGI, mod_wsgi, or gevent, you can get them running without worrying about
how they implement the WSGI standard.

However, knowing the WSGI standard and how these frameworks and containers
implement WSGI should be on your learning checklist though as you become
a more experienced Python web developer.

Official WSGI specifications

The WSGI standard v1.0 is specified in
PEP 0333. As of September 2010,
WSGI v1.0 is superseded by
PEP 3333, which defines the
v1.0.1 WSGI standard. If you're working with Python 2.x and you're compliant
with PEP 0333, then you're also compliant with 3333. The newer version is
simply an update for Python 3 and has instructions for how unicode should
be handled.

Example web server configuration

A web server's configuration specifies what requests should be passed to
the WSGI server to process. Once a request is processed and generated by the
WSGI server, the response is passed back through the web server and onto
the browser.

For example, this Nginx web server's configuration specifics
Nginx should handle static assets (such as images, JavaScript, and CSS
files) under the /static directory and pass all other requests to the WSGI
server running on port 8000:

# this specifies that there is a WSGI server running on port 8000upstreamapp_server_djangoapp{serverlocalhost:8000fail_timeout=0;}# Nginx is set up to run on the standard HTTP port and listen for requestsserver{listen80;#nginxshouldserveupstaticfilesandneversendtotheWSGIserverlocation/static{autoindexon;alias/srv/www/assets;}#requeststhatdonotfallunder/staticarepassedontotheWSGI#serverthatwasspecifiedaboverunningonport8000location/{proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerHost$http_host;proxy_redirectoff;if(!-f$request_filename){proxy_passhttp://app_server_djangoapp;break;}}}

Note that the above code is a simplified version of a production-ready Nginx
configuration. For real SSL and non-SSL templates, take a look at the
Underwear web server templates on GitHub.

WSGI servers

There is a comprehensive list of WSGI servers on the
WSGI Read the Docs page.
The following are WSGI servers based on community recommendations.

The Python community made a long effort to
transition from mod_python
to the WSGI standard. That transition period is now complete and an
implementation of WSGI should always be used instead mod_python.

Nicholas Piël wrote an interesting benchmark blog post of
Python WSGI servers.
Note that the post is a few years old. Benchmarks should be considered
for their specific tested scenarios and not quickly extrapolated as general
"this server is faster than this other server" results.