当前位置: 首页 > news >正文

Python 的 WSGI 简单了解

从 flask 的 hello world 说起

直接讨论 WSGI,很多人可能没有概念,我们还是先从一个简单的 hello world 程序开始吧。

from flask import Flaskapp  = Flask(__name__)@app.route("/", methods=['GET'])
def index():return "Hello world!"if __name__ == '__main__':app.run(port=8000)

在这里插入图片描述

相信只要使用过 flask 框架或者其它 Python 框架的人,应该都会见过这个警告。这个警告的意思是:这是一个开发服务器。不要在生产环境使用它。使用一个生产的 WSGI 服务器来代替。

那么什么是 WSGI 呢?

WSGI is the Web Server Gateway Interface. It is a specification that describes how a web server communicates with web applications, and how web applications can be chained together to process one request.
WSGI 是 Web 服务器网关接口。它是一个规范,描述了web服务器如何与web应用程序通信,以及如何将web应用程序链接在一起以处理一个请求。

这里来看一个简略的时序图:
它描述了用户通过浏览器上网的过程,浏览器发送请求到 Server,Server 再把请求交给 Application 来处理,最后返回响应数据给用户的过程。(通常来说,请求在到达 Server 之前,还会先经过一个反向代理服务器,例如 nginx 或者 apache 等)
在这里插入图片描述
上面这个时序图其实可以看做是大部分网络应用程序的模式了。从请求到达应用和响应返回给用户,这个过程其实是固定的。所以,一个web应用的区别就在于它对请求的处理方式上,例如:用户使用百度、搜狗亦或是谷歌浏览器,对于用户的感知其实是相同的(尽管它们内部的实现并不相同,这里也不考虑用户的体验问题,哈哈)。

什么是 WSGI?

我们都知道通用的部分可以抽取出来,做成一个组件供其它应用使用。所以 WebServer 就是这样一个组件,它负责接收用户的请求,然后交给用户的Web应用,等到它处理完成之后,再把响应数据返回给调用者。所以,WebServer 要和 WebApplication 进行交互,那就需要定义一个协议或者更专业一点叫做接口,因此这就是 WSGI。而实现 WSGI 接口的,我们则成为 WebServer 或者 WSGI Server。

注:如果你有 java web 的背景,相信你应该使用过 tomcat,也听过 servlet API。其实,它们之间的关系和WSGI服务器与 WSGI接口的关系是类似的。

它的接口其实很简单,只要 Web 框架实现了它,就可以使用各种实现了 WSGI 接口的服务器了。
在这里插入图片描述
我们常用的 Web 框架有:falsk、django 等;WSGI 服务器有:gunicorn、uWSGI等。

对于我们入门学习来说,它其实也是很简单的,我们也不需要了解那么多。对于Web 框架的作者来说,他们需要提供一个带两个参数的可调用对象即可:

callable(environ, start_response)

下面是 Python 的 PEP3333 中提供的两个简单例子,一个是函数实现,一个是类实现,它们都是一个 Web Application。

HELLO_WORLD = b"Hello world!\n"def simple_app(environ, start_response):"""Simplest possible application object"""status = '200 OK'response_headers = [('Content-type', 'text/plain')]start_response(status, response_headers)return [HELLO_WORLD]class AppClass:"""Produce the same output, but using a class(Note: 'AppClass' is the "application" here, so calling itreturns an instance of 'AppClass', which is then the iterablereturn value of the "application callable" as required bythe spec.If we wanted to use *instances* of 'AppClass' as applicationobjects instead, we would have to implement a '__call__'method, which would be invoked to execute the application,and we would need to create an instance for use by theserver or gateway."""def __init__(self, environ, start_response):self.environ = environself.start = start_responsedef __iter__(self):status = '200 OK'response_headers = [('Content-type', 'text/plain')]self.start(status, response_headers)yield HELLO_WORLD

Python 官方提供了一个简单的 WSGI 实现,我们就以上面这两个例子为例来演示一下:

from wsgiref.simple_server import make_serverif __name__ == '__main__':with make_server("127.0.0.1", 8000, simple_app) as httpd:print("Server started on port 8000...")httpd.serve_forever()

在这里插入图片描述
在这里插入图片描述

使用基于类的实现,效果也是一样的,通常更推荐使用类的方式,因为可以利用面向对象的思想来编程。

from wsgiref.simple_server import make_serverif __name__ == '__main__':with make_server("127.0.0.1", 8000, AppClass) as httpd:print("Server started on port 8000...")httpd.serve_forever()

甚至,我们还可以再进行一步,使用这个 Python 自带的 WSGI 服务来运行最开始的 flask 的 hello world:

from wsgiref.simple_server import make_serverfrom flask import Flaskapp  = Flask(__name__)@app.route("/", methods=['GET'])
def index():return "Hello world!"if __name__ == '__main__':with make_server("127.0.0.1", 8000, app) as httpd:print("Server started on port 8000...")httpd.serve_forever()

这样再次运行它,连警告也没有了。不过,自带的这个只是一个简单的实现,官方也并不推荐在生产环境使用它。但是 flask 其实并不知道,我们使用了什么 WSGI 服务器,因为它也不关心这个。

在这里插入图片描述

在这里插入图片描述

flask 背后的秘密

甚至不需要深入 flask 的源码,只需要浅浅的一探,我们就能明白为什么上面那样做的可以的了。这是 Flask 类的源码的一小部分,其它的无需解释了,我相信这是不言自明的。

class Flask(App):"""The flask object implements a WSGI application and acts as the centralobject.  """def wsgi_app(self, environ: WSGIEnvironment, start_response: StartResponse) -> cabc.Iterable[bytes]:...def __call__(self, environ: WSGIEnvironment, start_response: StartResponse) -> cabc.Iterable[bytes]:"""The WSGI server calls the Flask application object as theWSGI application. This calls :meth:`wsgi_app`, which can bewrapped to apply middleware."""return self.wsgi_app(environ, start_response)

总结

关于 WSGI,它的文档就直接说明了,对于 Web 开发者来说,其实并不用去了解它。因为我们的工作重点其实是请求的处理,对于我上面序列图中的大部分操作都不需要关系了,它隐藏了很多的细节,使得我们可以更加专注于自己的工作内容。不过,我觉得简单的了解一下也是蛮好的,也不需要深入的了解,浅尝辄止即可。对于我们工作的整个领域都有一个概览,然后还是专注于自己工作的重点内容上。

相关文章:

Python 的 WSGI 简单了解

从 flask 的 hello world 说起 直接讨论 WSGI,很多人可能没有概念,我们还是先从一个简单的 hello world 程序开始吧。 from flask import Flaskapp Flask(__name__)app.route("/", methods[GET]) def index():return "Hello world!&q…...

基于stm32使用ucgui+GUIBuilder开发ui实例

1 项目需求 1.1 基于Tft 触摸屏实现一个自锁按键 1.2 按键在按下后背景色需要进行变化,以凸显当前按键状态(选中or 未选中) 1.3 按键选中时对某一gpio输出低电平,非选中时输出高电平 2 移植 ucgui UCGUI的文件数量很大&#x…...

Spring扩展点系列-ApplicationContextAwareProcessor

文章目录 简介源码分析示例代码示例一:扩展点的执行顺序运行示例一 示例二:获取配置文件值配置文件application.properties内容定义工具类ConfigUtilcontroller测试调用运行示例二 示例三:实现ResourceLoaderAware读取文件ExtendResourceLoad…...

基于Keil软件实现实时时钟(江协科技HAL库)

实时时钟实验是基于江协科技STM32的HAL库工程模板创建的(可以在作品“基于江科大STM32创建的HAL库工程模板”中的结尾处获取工程模板的百度网盘链接) 复制“OLED显示”的工程文件——“4-1 OLED显示屏”,并命名为“12-2 实时时钟 ”。打开工程,把下面的程序复制到相应的文…...

dedecms靶场(四种webshell姿势)

进入靶场 姿势一:过文件管理器上传WebShell 步骤一:登录后台 /dede 步骤二:核心-》文件式管理-》文件上传-》上传一句话木马 点击 步骤三:进行蚁剑连接 姿势二:修改模板文件拿WebShell 步骤一:模板-》默认…...

PHP:强大的Web开发语言

PHP:强大的Web开发语言 一、PHP 简介及优势 PHP 的基本概念 PHP(PHP: Hypertext Preprocessor)即 “超文本预处理器”,是一种通用开源脚本语言,最初由 Rasmus Lerdorf 于 1994 年创建。它可以在服务器上执行&#xf…...

06_Python数据类型_元组

Python的基础数据类型 数值类型:整数、浮点数、复数、布尔字符串容器类型:列表、元祖、字典、集合 元组 元组(Tuple)是一种不可变的序列类型,与列表类似,但有一些关键的区别。本质:只读的列表…...

【Vue】- ref获取DOM元素和购物车案例分析

文章目录 知识回顾前言源码分析1. ref2. 购物车案例分析3. 购物车计算、全选 拓展知识数据持久化localStorage 总结 知识回顾 前言 元素上使用 ref属性关联响应式数据&#xff0c;获取DOM元素 步骤 ● 创建 ref > const hRef ref(null) ● 模板中建立关联 > <h1 re…...

【AI大模型】ChatGPT模型原理介绍(下)

目录 &#x1f354; GPT-3介绍 1.1 GPT-3模型架构 1.2 GPT-3训练核心思想 1.3 GPT-3数据集 1.4 GPT-3模型的特点 1.5 GPT-3模型总结 &#x1f354; ChatGPT介绍 2.1 ChatGPT原理 2.2 什么是强化学习 2.3 ChatGPT强化学习步骤 2.4 监督调优模型 2.5 训练奖励模型 2.…...

Python数据分析与可视化实战指南

在数据驱动的时代&#xff0c;Python因其简洁的语法、强大的库生态系统以及活跃的社区&#xff0c;成为了数据分析与可视化的首选语言。本文将通过一个详细的案例&#xff0c;带领大家学习如何使用Python进行数据分析&#xff0c;并通过可视化来直观呈现分析结果。 一、环境准…...

react18基础教程系列-- 框架基础理论知识mvc/jsx/createRoot

react的设计模式 React 是 mvc 体系&#xff0c;vue 是 mvvm 体系 mvc: model(数据)-view(视图)-controller(控制器) 我们需要按照专业的语法去构建 app 页面&#xff0c;react 使用的是 jsx 语法构建数据层&#xff0c;需要动态处理的的数据都要数据层支持控制层: 当我们需要…...

牛客周赛 Round 60 折返跑(组合数学)

题目链接&#xff1a;题目 大意&#xff1a; 在 1 1 1到 n n n之间往返跑m趟&#xff0c;推 m − 1 m-1 m−1次杆子&#xff0c;每次都向中间推&#xff0c;不能推零次&#xff0c;问有多少种推法&#xff08;mod 1e97&#xff09;。 思路&#xff1a; 一个高中学过的组合数…...

深入浅出Java匿名内部类:用法详解与实例演示

匿名内部类&#xff08;Anonymous Inner Class&#xff09;在Java中是一种非常有用的特性&#xff0c;它允许你在一个类的定义中直接创建并实例化一个内部类&#xff0c;而不需要为这个内部类指定一个名字。匿名内部类通常用于以下几种情况&#xff1a; 实现接口&#xff1a;当…...

数据库MySQL、Mariadb、PostgreSQL、MangoDB、Memcached和Redis详细介绍

以下是一些常见的后端开发数据库选型&#xff1a; 关系型数据库&#xff08;RDBMS&#xff09;&#xff1a;关系型数据库是最常见的数据库类型&#xff0c;使用表格和关系模型来存储和管理数据。常见的关系型数据库包括MySQL、PostgreSQL和Oracle等。这些数据库适合处理结构化数…...

【ArcGIS Pro实操第七期】栅格数据合并、裁剪及统计:以全球不透水面积为例

【ArcGIS Pro实操第七期】批量裁剪&#xff1a;以全球不透水面积为例 准备&#xff1a;数据下载ArcGIS Pro批量裁剪数据集1 数据拼接2 数据裁剪3 数据统计&#xff1a;各栅格取值3.1 栅格计算器-精确提取-栅格数据特定值3.2 数据统计 4 不透水面积变化分析 参考 准备&#xff1…...

【Linux】Image、zImage与uImage的区别

1、Image 1.1 什么是 Image Image 是一种未压缩的 Linux 内核镜像文件&#xff0c;包含了内核的所有代码、数据和必要的元信息。它是 Linux 内核在编译过程中生成的一个原始的二进制文件&#xff0c;未经过任何压缩或额外的封装处理。由于未压缩&#xff0c;Image 文件相对较…...

算子加速(3):自定义cuda扩展

需要自定义某个层,或有时候用c++实现你的操作(c++扩展)可能会更好: 例如:需要实现一个新型的激活函数例如: bevfusion用cuda实现bevpool加速自定义扩展的步骤 (1) 首先用纯pytorch和python 实现我们所需的功能,看看效果再决定要不要进一步优化(2) 明确优化方向,用C++ (或CU…...

信息安全数学基础(14)欧拉函数

前言 在信息安全数学基础中&#xff0c;欧拉函数&#xff08;Eulers Totient Function&#xff09;是一个非常重要的概念&#xff0c;它与模运算、剩余类、简化剩余系以及密码学中的许多应用紧密相关。欧拉函数用符号 φ(n) 表示&#xff0c;其中 n 是一个正整数。 一、定义 欧…...

7-17 汉诺塔的非递归实现

输入样例: 3输出样例: a -> c a -> b c -> b a -> c b -> a b -> c a -> c 分析&#xff1a; 不会汉罗塔的uu们&#xff0c;先看看图解&#xff1a; 非递归代码&#xff1a; #include<iostream> #include<stack> using namespace std; s…...

word文档无损原样转pdf在windows平台使用python调用win32com使用pip安装pywin32

前提&#xff1a; windows环境下&#xff0c;并且安装了office套装&#xff0c;比如word,如果需要调用excel.也需要安装。在另外的文章会介绍。这种是直接调用word的。所以还原度会比较高。 需求&#xff1a; word文档转pdf,要求使用命令行形式&#xff0c;最终发布为api接口…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...