0

0

一定要懂WSGI是什么

coldplay.xixi

coldplay.xixi

发布时间:2020-11-10 17:01:04

|

2262人浏览过

|

来源于juejin

转载

python视频教程栏目介绍wsgi。

一定要懂WSGI是什么

写了几年的python web,却还不知道WSGI是什么东西,是不是大有人在。 说来也正常,因为作为开发者很少需要去了解wsgi是什么,也能把网站做出来。

但是如果你想自己写个web框架玩玩,就不得不去了解wsgi了。

回顾一下,我们在用python做web开发的时候,一般基于某个web框架来开发,django或者是flask等其它框架。 业务开发完成后,就要部署到某台服务器中提供对外的访问。

这时候你去网上一搜,他们都会告诉你需要用 gunicorn或者是uwsgi 来部署。 那么gunicorn、uwsgi 又是什么玩意。

看这个图你就明白了,图我是从网上找的

这里的uwsgi或者gunicorn扮演的角色就是web服务器的角色,这里的服务器是软件层面的服务器,用于处理浏览器发过来的HTTP请求以及将响应结果返回给前端。而Web框架的主要任务就是处理业务逻辑生成结果给web服务器,再由web服务器返回给浏览器。

而web框架和web服务器之间的通信需要遵循一套规范,这个规范就是WSGI了。

为什么要搞这么一套规范出来? 规范就是为了统一标准,方便大家所用

想象一下,我们手机充电的接口现在都是Type-c的,Type-c 就是一种规范, 手机厂商按照这个规范去生产手机, 充电器厂商按照Type-c的规范生产充电器,不同厂商的手机就可以和不同厂商的充电器搭配使用。 而苹果却自成一套规范,最后导致Android充电器无法给苹果充电。

![

](p9-juejin.byteimg.com/tos-cn-i-k3…)

那如何写出一个符合 WSGI规范的应用(框架)程序和服务器呢?

易想商务网
易想商务网

YxB2B商务网是易想网络旗下的门户型B2B行业网站系统,采用先进的标签技术和静态生成技术,通过网站后台管理轻松实现网站前台多种风格和会员网站多风格,让每一个只要懂得简单网页制作常识的网友,轻松制作出精美专业的的行业商务网站系统。系统高速、稳定、安全,完全仿阿里巴巴功能设计,有供应信息、求购信息、产品库、公司库、专项商机、行业信息、展会服务、人才市场、会员助手、网商博客、商友论坛、全方位搜索等栏目

下载

如上图所示,左边是web服务器,右边是web框架,或者说应用程序。

应用程序

WSGI规定应用程序必须是一个可调用对象(可调用对象可以是函数,也可以是类,还可以是实现了 __call__的实例对象),而且必须接受两个参数,该对象的返回值必须是可迭代对象。

我们可以写个最简单的应用程序的例子

HELLO_WORLD = b"Hello world!\n"def application(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)    return [HELLO_WORLD]复制代码

application 是一个函数,肯定是可调用对象,然后接收两个参数,两个参数分别是:environ和start_response

  • environ是一个字典,里面储存了HTTP request相关的所有内容,比如header、请求参数等等
  • start_response是一个WSGI 服务器传递过来的函数,用于将response header,状态码传递给Server。

调用 start_response 函数负责将响应头、状态码传递给服务器, 响应体则由application函数返回给服务器, 一个完整的http response 就由这两个函数提供。

但凡是实现了wsgi的web框架都会有这样一个可调用对象

服务器

WSGI 服务器端做的事情就是每次接收HTTP请求,构建environ对象,然后调用application对象,最后将HTTP Response返回给浏览器。

下面就是一个完整的wsgi server 的代码

import socketimport sysfrom io import StringIOclass WSGIServer(object):
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    request_queue_size = 1

    def __init__(self, server_address):
        # Create a listening socket
        self.listen_socket = listen_socket = socket.socket(
            self.address_family,
            self.socket_type
        )        # Allow to reuse the same address
        listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        # Bind
        listen_socket.bind(server_address)        # Activate
        listen_socket.listen(self.request_queue_size)        # Get server host name and port
        host, port = self.listen_socket.getsockname()[:2]
        self.server_name = socket.getfqdn(host)
        self.server_port = port        # Return headers set by Web framework/Web application
        self.headers_set = []    def set_app(self, application):
        self.application = application    def serve_forever(self):
        listen_socket = self.listen_socket        while True:            # New client connection
            self.client_connection, client_address = listen_socket.accept()            # Handle one request and close the client connection. Then
            # loop over to wait for another client connection
            self.handle_one_request()    def handle_one_request(self):
        self.request_data = request_data = self.client_connection.recv(1024)        # Print formatted request data a la 'curl -v'
        print(''.join(            '< {line}\n'.format(line=line)            for line in request_data.splitlines()
        ))
        self.parse_request(request_data)        # Construct environment dictionary using request data
        env = self.get_environ()        # It's time to call our application callable and get
        # back a result that will become HTTP response body
        result = self.application(env, self.start_response)        # Construct a response and send it back to the client
        self.finish_response(result)    def parse_request(self, text):
        request_line = text.splitlines()[0]
        request_line = request_line.rstrip('\r\n')        # Break down the request line into components
        (self.request_method,  # GET
         self.path,  # /hello
         self.request_version  # HTTP/1.1
         ) = request_line.split()    def get_environ(self):
        env = {}        # The following code snippet does not follow PEP8 conventions
        # but it's formatted the way it is for demonstration purposes
        # to emphasize the required variables and their values
        #
        # Required WSGI variables
        env['wsgi.version'] = (1, 0)
        env['wsgi.url_scheme'] = 'http'
        env['wsgi.input'] = StringIO.StringIO(self.request_data)
        env['wsgi.errors'] = sys.stderr
        env['wsgi.multithread'] = False
        env['wsgi.multiprocess'] = False
        env['wsgi.run_once'] = False
        # Required CGI variables
        env['REQUEST_METHOD'] = self.request_method  # GET
        env['PATH_INFO'] = self.path  # /hello
        env['SERVER_NAME'] = self.server_name  # localhost
        env['SERVER_PORT'] = str(self.server_port)  # 8888
        return env    def start_response(self, status, response_headers, exc_info=None):
        # Add necessary server headers
        server_headers = [
            ('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'),
            ('Server', 'WSGIServer 0.2'),
        ]
        self.headers_set = [status, response_headers + server_headers]        # To adhere to WSGI specification the start_response must return
        # a 'write' callable. We simplicity's sake we'll ignore that detail
        # for now.
        # return self.finish_response

    def finish_response(self, result):
        try:
            status, response_headers = self.headers_set
            response = 'HTTP/1.1 {status}\r\n'.format(status=status)            for header in response_headers:
                response += '{0}: {1}\r\n'.format(*header)
            response += '\r\n'
            for data in result:
                response += data            # Print formatted response data a la 'curl -v'
            print(''.join(                '> {line}\n'.format(line=line)                for line in response.splitlines()
            ))
            self.client_connection.sendall(response)        finally:
            self.client_connection.close()


SERVER_ADDRESS = (HOST, PORT) = 'localhost', 8080def make_server(server_address, application):
    server = WSGIServer(server_address)
    server.set_app(application)    return serverif __name__ == '__main__':
    httpd = make_server(SERVER_ADDRESS, application)
    print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))
    httpd.serve_forever()复制代码

当然,如果只是写个用于开发环境用的server,用不着这么麻烦自己造轮子,因为python内置模块中就提供有 wsgi server 的功能。

from wsgiref.simple_server import make_server
srv = make_server('localhost', 8080, application)
srv.serve_forever()复制代码

只要3行代码就可以提供wsgi服务器,是不是超级方便,最后来访问测试下浏览器发起一个请求的效果

以上就是wsgi简介,深入了解wsgi可以熟悉下PEP333

相关免费学习推荐:python视频教程

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python Web 框架 Django 深度开发
Python Web 框架 Django 深度开发

本专题系统讲解 Python Django 框架的核心功能与进阶开发技巧,包括 Django 项目结构、数据库模型与迁移、视图与模板渲染、表单与认证管理、RESTful API 开发、Django 中间件与缓存优化、部署与性能调优。通过实战案例,帮助学习者掌握 使用 Django 快速构建功能全面的 Web 应用与全栈开发能力。

145

2026.02.04

Python Flask框架
Python Flask框架

本专题专注于 Python 轻量级 Web 框架 Flask 的学习与实战,内容涵盖路由与视图、模板渲染、表单处理、数据库集成、用户认证以及RESTful API 开发。通过博客系统、任务管理工具与微服务接口等项目实战,帮助学员掌握 Flask 在快速构建小型到中型 Web 应用中的核心技能。

98

2025.08.25

Python Flask Web框架与API开发
Python Flask Web框架与API开发

本专题系统介绍 Python Flask Web框架的基础与进阶应用,包括Flask路由、请求与响应、模板渲染、表单处理、安全性加固、数据库集成(SQLAlchemy)、以及使用Flask构建 RESTful API 服务。通过多个实战项目,帮助学习者掌握使用 Flask 开发高效、可扩展的 Web 应用与 API。

78

2025.12.15

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1708

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

549

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2332

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

42

2026.01.19

android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

329

2023.08.14

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

6

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Python Web框架Flask进阶视频教程
Python Web框架Flask进阶视频教程

共12课时 | 2.9万人学习

Python Web框架Flask入门视频教程
Python Web框架Flask入门视频教程

共7课时 | 2.6万人学习

Flask实战视频教程
Flask实战视频教程

共9课时 | 2.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号