python通过wsgi实现web服务

前言

我们都知道,平时我们使用python来写web服务的时候一般都会选择主流框架,flask,django等,那么这些框架是怎么实现web服务的呢?就需要我们了解一下wsgi了。

什么是wsgi?

PythonWeb服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是Python应用程序或框架和Web服务器之间的一种接口,已经被广泛接受, 它已基本达成它的可移植性方面的目标。
WSGI 没有官方的实现, 因为WSGI更像一个协议. 只要遵照这些协议,WSGI应用(Application)都可以在任何服务器(Server)上运行, 反之亦然。
WSGI标准在 PEP 333 中定义并被许多框架实现,其中包括现广泛使用的django框架。
那么,我们为什么要用wsgi呢?首先我们先了解下web工作过程:

1、用户操作操作浏览器发送请求;
2、请求转发至对应的web服务器
3、web服务器将请求转交给web应用程序,web应用程序处理请求
4、web应用将请求结果返回给web服务器,由web服务器返回用户响应结果
5、浏览器收到响应,向用户展示

通过上面的内容我们了解到,请求时web服务器是要和应用进行通信的,但是web服务器和Python WEB的开发框架都有很多种,为了我们开发方便所以就有了一套通信标准。

web服务器在将请求转交给web应用程序之前,需要先将http报文转换为WSGI规定的格式。
WSGI规定,Web程序必须有一个可调用对象,且该可调用对象接收两个参数,返回一个可迭代对象:

1、environ:字典,包含请求的所有信息
2、start_response:在可调用对象中调用的函数,用来发起响应,参数包括状态码,headers等
那么我们了解了wsgi就让我们现在来写一个web服务吧

demo展示

这是我们的文件结构,一个是http处理函数,一个用来启动服务器
python通过wsgi实现web服务_第1张图片
这是我们的http处理函数,用来获取environ字典中的path_info,也就是获取请求路径,然后在前端展示。
python通过wsgi实现web服务_第2张图片

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def helloword(environ, start_response):
    status = "200 OK"
    response_headers = [('Content-Type', 'text/html')]
    start_response(status, response_headers)
    path = environ['PATH_INFO'][1:] or 'hello word'
    return [b'

%s

'
% path.encode()]

这是用来启动WSGI服务器处理验证的方法,使用Python内置的WSGI服务器模块wsgiref,编写test1.py:
python通过wsgi实现web服务_第3张图片

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
WSGI服务器实现
"""
from wsgiref.simple_server import make_server
from test2 import helloword

def main():
    server = make_server('localhost', 8001, helloword())
    print('Serving HTTP on port 8001...')
    server.serve_forever()

if __name__ == '__main__':
    main()

然后我们运行test1,服务就启动了
python通过wsgi实现web服务_第4张图片
浏览器输入localhost:8001就能看见test2中返回的内容了
python通过wsgi实现web服务_第5张图片

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)

wsgiref.simple_server中的demo

python通过wsgi实现web服务_第6张图片
好啦,大家快去试试吧!

你可能感兴趣的:(python,python,http,wsgi)