python wsgi

wsgi是什么

  • wsgi(Web Server Gateway Interface)web服务器网关接口,是一套在httpserver(比如nginx,apache)和python程序之间传递的接口标准,WSGI 是基于现存的 CGI 标准而设计的.
  • wsgi在PEP333中定义
  • WSGI 的设计参考了 Java 的 servlet
  • python 中,作为wsgi服务器的组件有uwsgi,gunicorn等。
  • 常见的http请求的处理流程如下所示:

Nginx-->(wsgi)gunicorn-->framework-->application
wsgi工作在wsgi服务器和web服务器的中间,一般是使用nginx来进行反向代理。然后使用gunicorn来当wsgi服务器。
其中,nginx一般用作负载均衡处理,gunicorn用于http请求的解析和封装,为framework提供梳理好的http数据。而application则用于根据框架请求的数据进行相应的处理。

wsgi的规范:

  1. wsgi规定每个 python 程序(Application)必须是一个可调用的对象(实现了_call_ 函数的方法或者类),接受两个参数 environ(WSGI 的环境信息) 和 start_response(开始响应请求的函数),并且返回 iterable
    其中:
    - environ 和 start_response 由 http server 提供并实现
    - environ 变量是包含了环境信息的字典
    - Application 内部在返回前调用 start_response
    - start_response也是一个 callable,接受两个必须的参数,status(HTTP状态)和 response_headers(响应消息的头)
    - 可调用对象要返回一个值,这个值是可迭代的。
    2:

wsgi实现:

wsgi 应用端实现:

# 1. 可调用对象是一个函数
def application(environ, start_response):

   response_body = 'The request method was %s' % environ['REQUEST_METHOD']

   # HTTP response code and message
   status = '200 OK'

   # 应答的头部是一个列表,每对键值都必须是一个 tuple。
   response_headers = [('Content-Type', 'text/plain'),
                       ('Content-Length', str(len(response_body)))]

   # 调用服务器程序提供的 start_response,填入两个参数
   start_response(status, response_headers)

   # 返回必须是 iterable
   return [response_body]    

# 2. 可调用对象是一个类
class AppClass:
    """这里的可调用对象就是 AppClass 这个类,调用它就能生成可以迭代的结果。
        使用方法类似于: 
        for result in AppClass(env, start_response):
             do_somthing(result)
    """

    def __init__(self, environ, start_response):
        self.environ = environ
        self.start = start_response

    def __iter__(self):
        status = '200 OK'
        response_headers = [('Content-type', 'text/plain')]
        self.start(status, response_headers)
        yield "Hello world!\n"

# 3. 可调用对象是一个实例 
class AppClass:
    """这里的可调用对象就是 AppClass 的实例,使用方法类似于: 
        app = AppClass()
        for result in app(environ, start_response):
             do_somthing(result)
    """

    def __init__(self):
        pass

    def __call__(self, environ, start_response):
        status = '200 OK'
        response_headers = [('Content-type', 'text/plain')]
        self.start(status, response_headers)
        yield "Hello world!\n"

wsig是处于web server 和web application中间的一层,所以
wsgi server端实现:

import os, sys

def run_with_cgi(application):    # application 是程序端的可调用对象
    # 准备 environ 参数,这是一个字典,里面的内容是一次 HTTP 请求的环境变量
    environ = dict(os.environ.items())
    environ['wsgi.input']        = sys.stdin
    environ['wsgi.errors']       = sys.stderr
    environ['wsgi.version']      = (1, 0)
    environ['wsgi.multithread']  = False
    environ['wsgi.multiprocess'] = True
    environ['wsgi.run_once']     = True            
    environ['wsgi.url_scheme'] = 'http'

    headers_set = []
    headers_sent = []

    # 把应答的结果输出到终端
    def write(data):
        sys.stdout.write(data)
        sys.stdout.flush()

    # 实现 start_response 函数,根据程序端传过来的 status 和 response_headers 参数,
    # 设置状态和头部
    def start_response(status, response_headers, exc_info=None):
        headers_set[:] = [status, response_headers]
          return write

    # 调用客户端的可调用对象,把准备好的参数传递过去
    result = application(environ, start_response)

    # 处理得到的结果,这里简单地把结果输出到标准输出。
    try:
        for data in result:
            if data:    # don't send headers until body appears
                write(data)
    finally:
        if hasattr(result, 'close'):
            result.close()

参考连接:
wsgi PEP333翻译
WSGI协议的原理及实现

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