Modern Python Web Development Basics: From WSGI to Web Framework
1. Behind every web request, "questions and answers" are being performed.
Whether you are reading the news, browsing the mall, or ordering takeout on your mobile phone, the underlying communication logic can be condensed into a standard HTTP question and answer:
- The client (browser or App) makes a request according to the HTTP specification, such as
GET /index.html HTTP/1.1。 - The server receives the request and parses the method, path, request header and other information.
- Based on the request content, the server decides whether to directly return the static file or call a piece of dynamic code to generate the page.
- The server encapsulates the generated content into an HTTP response and returns it to the client.
- The client receives the response and renders the interface you see.
In this process, web servers such as Nginx and Apache are efficient enough to handle static content such as images, CSS, and pure HTML. But once it involves "the home page that Zhang San saw after logging in" and "Li Si's order details", which are dynamic content that can be used by thousands of people, there must be an environment that can run the code. This gave rise to a type of interface specification that determines "how the server calls the application" - WSGI is the most common set of conventions in the Python world.
2. WSGI: The “universal socket” for all Python web applications
The full name of WSGI is Web Server Gateway Interface, which is formally defined by PEP 333 and PEP 3333. It is not a library or a framework, but a set of function call level protocols - as long as your application and your server comply with this set of rules, no matter what implementation they use, they can be seamlessly connected.
2.1 The simplest WSGI application is actually just a few lines
A legal WSGI application only needs to meet two rules:
- Must be a callable (function, class instance, or even a callable with
__call__Any object of the method will work); - Must receive two fixed parameters and return an iterable byte stream.
The following is an example of a sparrow that is small but has all the internal organs:
Just run this code in a suitable WSGI server and it will become a "live" website.
2.2 All the secrets are hidden in the two parameters
① environ: A large dictionary filled with requested information
environIs a standard Python dict, which holds all details of the current request and some server environment variables. Commonly used keys include:
- Original HTTP message
REQUEST_METHOD:GET、POST、PUT、DELETE……PATH_INFO: Path part, such as/user/profileQUERY_STRING:?The following query parameters, such asname=alice&age=20HTTP_USER_AGENT: The identifier of the browser or client
- Environment and container information
SERVER_NAME、SERVER_PORT:Current server address and portwsgi.input: A readable file stream specifically used to read the request body of POST requests.
Tip: All HTTP request headers are in
environBring it with you in the cityHTTP_prefix, connected with capital letters and underscores, for exampleUser-Agent→HTTP_USER_AGENT。
② start_response: A callback that can only be called once
start_responseIt is a callback function provided by the WSGI server to the application. It must be called once before returning the response body. It is responsible for informing the client in advance "what the content you are about to receive looks like":
- The first parameter: status code in string form + status description, such as
'200 OK'、'404 Not Found'; - The second parameter: response header list, each element is
(Header-Name, Header-Value)A tuple of formats.
Call completedstart_responseAfter that, the application can return the response body data calmly.
3. Run first: test WSGI applications in situ using the Python standard library
You don’t need to install any third-party tools, Python comes with itwsgirefThe module is a WSGI reference server, which is very suitable for local development and debugging.
3.1 Set up an interactive local service in two steps
Step 1: Write the WSGI application
Save the code below asapp.py, which implements a simple application that can dynamically display names based on paths:
Step 2: Write a startup script
Create new fileserver.py,usewsgirefStart the server:
runpython server.py, and then access it in the browserhttp://localhost:8000/Tom, you will see the page dynamically display "Hello, Tom!", and print out the request method and User-Agent.
**At this point, you have created a pure WSGI Web applet. **
4. Why don’t we usually write WSGI directly? ——Framework is the key to productivity
Although the above example is simple, once the requirements are slightly more complex, such as:
- Parse JSON body from POST request;
- Design an elegant URL routing;
- Handling Cookies and Sessions;
- Defense against cross-site attacks, cross-domain requests...
You'll find that the underlying flexibility of WSGI becomes a liability. You need to handle a lot of repetitive and error-prone work yourself. As a result, Web frameworks naturally appeared on the scene - they crushed WSGI into pieces and encapsulated them into developer-friendly APIs, allowing you to focus on business logic rather than the underlying protocol.
4.1 The relationship between mainstream Python frameworks and WSGI
Taking Flask as an example, let's see how much the code is simplified when "dynamic path" is also implemented.
Manual routing using raw WSGI: (pseudocode)
Use Flask to write the same set of logic:
Route parsing, status code management, and error handling are all clearly arranged by the framework.
**The framework does not change the underlying rules of WSGI, it just writes the tedious ones for youif/elseand parameter dismantling. **
5. From development to launch: production-level deployment of WSGI applications
wsgirefIt is for developers to "play" locally and must not be used in production environments. When going online, we need to replace it with a professional WSGI server and cooperate with a reverse proxy to handle real traffic.
5.1 The most classic combination: Gunicorn + Nginx
- Gunicorn (Green Unicorn): A mature, high-performance WSGI server implemented in pure Python, supporting multiple worker processes to handle requests concurrently.
- Nginx: HTTP server/reverse proxy known as the "Swiss Army Knife", mainly responsible for:
- Return static files directly (much faster than Python service);
- Proxy dynamic requests to Gunicorn on the backend;
- Configure HTTPS and load balancing;
- Caching, current limiting, and resistance to simple attacks.
Simple deployment process
-
Install Gunicorn:
-
Use Gunicorn to start the application (assuming your application callable object is in
app.pymiddle namedynamic_wsgi_app):-w 4Indicates starting 4 work processes;-bSpecify the listening address and port.
-
Configure Nginx to forward domain name/public network requests to local port 8000. A minimalist configuration snippet is as follows:
After completion, restart Nginx. All user requests will first go through the high-performance Nginx, and then Gunicorn will execute your Python code. **This combination is also one of the most mainstream deployment methods for Python web applications. **
6. Looking forward: WSGI’s “asynchronous descendant” ASGI
Although WSGI unifies the Python Web world, it has an inherent weakness: synchronous blocking. When a request needs to wait for a database query or call a third-party API, the entire worker process will be stuck and unable to accept new requests, and the concurrency capability will be greatly restricted.
As a result, ASGI (Asynchronous Server Gateway Interface) came into being. It is powered by PEP 3156 and supports Python nativelyasync/awaitAsynchronous programming.
Modern frameworks such as FastAPI, Starlette, and django Channels are built based on ASGI by default, which can play great advantages in high-concurrency scenarios.
However, if you are currently using django (ASGI mode is also optional after 3.1) or traditional WSGI frameworks such as Flask, there is no need to worry -
- Under normal business request volume, Gunicorn's multi-worker mode is robust enough;
- Pass if necessary
uvicornWait for the ASGI server to provide a compatibility layer for WSGI applications, smooth transition.
7. Summary
- WSGI is the underlying protocol standard for Python Web development, which specifies the calling method between the server and the application, rather than a specific tool.
- Implementing a WSGI application is simple: write a receiving
environandstart_responseA callable object that returns an iterable byte stream. - In daily development, we usually do not write WSGI directly by hand, but rely on frameworks such as Flask, django, FastAPI, etc., which are still based on WSGI (or ASGI) at the bottom, but provide an extremely friendly programming experience.
- Production environment deployment must use a combination of "professional WSGI/ASGI servers (such as Gunicorn, uvicorn) + Nginx" to take into account performance, security and scalability.
- ASGI is the future trend of asynchronous web development, but WSGI is still the cornerstone of most projects today, and it is far from being completely outdated.
Understanding WSGI is equivalent to mastering the "Ren and Du" of Python web development. No matter how the framework changes, you can clearly see how it receives requests and generates responses, allowing you to write more solid code.

