在用Python Web开发时常常会遇到WSGI,因此WSGI究竟是什么呢?本文咱们一块儿来揭开WSGI神秘的面纱!html
先来看一下WSGI的介绍:前端
全称Python Web Server Gateway Interface,指定了web服务器和Python web应用或web框架之间的标准接口,以提升web应用在一系列web服务器间的移植性。 具体可查看 官方文档python
从以上介绍咱们能够看出:web
你可能会问,为何须要WSGI?浏览器
首先,咱们明确一下web应用处理请求的具体流程:服务器
能够看到,请求时Web服务器须要和web应用程序进行通讯,可是web服务器有不少种啊,Python web应用开发框架也对应多种啊,因此WSGI应运而生,定义了一套通讯标准。试想一下,若是不统一标准的话,就会存在Web框架和Web服务器数据没法匹配的状况,那么开发就会受到限制,这显然不合理的。app
既然定义了标准,那么WSGI的标准或规范是?框架
web服务器在将请求转交给web应用程序以前,须要先将http报文转换为WSGI规定的格式。函数
WSGI规定,Web程序必须有一个可调用对象,且该可调用对象接收两个参数,返回一个可迭代对象:工具
经过以上学习,一块儿实现一个简单WSGI服务吧
首先,咱们编写一个符合WSGI标准的一个http处理函数:
def hello(environ, start_response): status = "200 OK" response_headers = [('Content-Type', 'text/html')] start_response(status, response_headers) path = environ['PATH_INFO'][1:] or 'hello' return [b'<h1> %s </h1>' % path.encode()]
该方法负责获取environ字典中的path_info,也就是获取请求路径,而后在前端展现。
接下来,咱们须要一个服务器启动WSGI服务器用来处理验证,使用Python内置的WSGI服务器模块wsgiref,编写server.py:
# coding:utf-8 """ desc: WSGI服务器实现 """ from wsgiref.simple_server import make_server from learn_wsgi.client import hello def main(): server = make_server('localhost', 8001, hello) print('Serving HTTP on port 8001...') server.serve_forever() if __name__ == '__main__': main()
执行python server.py,浏览器打开"http://localhost:8001/a",便可验证。
经过实现一个简单的WSGI服务,咱们能够看到:经过environ能够获取http请求的全部信息,http响应的数据均可以经过start_response加上函数的返回值做为body。
固然,以上只是一个简单的案例,那么在python的Web框架内部是如何遵循WSGI规范的呢?以Flask举例,
Flask与WSGI
Flask中的程序实例app就是一个可调用对象,咱们建立app实例时所调用的Flask类实现了__call__方法,__call__方法调用了wsgi_app()方法,该方法完成了请求和响应的处理,WSGI服务器经过调用该方法传入请求数据,获取返回数据:
def wsgi_app(self, environ, start_response): ctx = self.request_context(environ) error = None try: try: ctx.push() response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: # noqa: B001 error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None ctx.auto_pop(error) def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response)
Flask的werkzeug库是一个很是优秀的WSGI工具库,具体的实现咱们以后再详细学习。
以上。