码迷,mamicode.com
首页 > 其他好文 > 详细

PEP 3333中对WSGI的简单示例

时间:2015-02-25 18:19:27      阅读:106      评论:0      收藏:0      [点我收藏+]

标签:

  本文只是对PEP3333中关于WSGI的例子的一个简单的记录,方便自己将来查看,若需要详细的信息,请自行查看PEP 3333的官方文档

WSGI中定义,application端是一个callable term(可以是function,class,method或者是一个实现了__call__方法的实例等),接受两个位置参数(名称不做要求):environ和start_response。

environ是一个标准的python dict对象(不可以是子类),用于保存系统需要的变量。

start_response是一个callable term,接受两个位置参数和一个可选参数,其形式如

start_response(status, response_headers, exc_info=None)

status是一个字符串,形如"200 OK"或者"404 NOT FOUND",状态码和Message以单个空白格分离。

response_headers是一个形如[(header_name, header_value), ...]的列表。

exc_info用于在发生错误时向浏览器输出信息。

start_response必须返回一个形如write(data)的callable,用于向浏览器输出信息。

 

当application被server调用时,必须返回一个iterable的bytestrings或者是zero(可以使用yield返回一个生成器)。

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 it
    returns an instance of ‘AppClass‘, which is then the iterable
    return value of the "application callable" as required by
    the spec.

    If we wanted to use *instances* of ‘AppClass‘ as application
    objects 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 the
    server or gateway.
    """

    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

 

server端的示例代码如下:

import os, sys

enc, esc = sys.getfilesystemencoding(), surrogateescape

def unicode_to_wsgi(u):
    # Convert an environment variable to a WSGI "bytes-as-unicode" string
    return u.encode(enc, esc).decode(iso-8859-1)

def wsgi_to_bytes(s):
    return s.encode(iso-8859-1)

def run_with_cgi(application):
    environ = {k: unicode_to_wsgi(v) for k,v in os.environ.items()}
    environ[wsgi.input]        = sys.stdin.buffer
    environ[wsgi.errors]       = sys.stderr
    environ[wsgi.version]      = (1, 0)
    environ[wsgi.multithread]  = False
    environ[wsgi.multiprocess] = True
    environ[wsgi.run_once]     = True

    if environ.get(HTTPS, off) in (on, 1):
        environ[wsgi.url_scheme] = https
    else:
        environ[wsgi.url_scheme] = http

    headers_set = []
    headers_sent = []

    def write(data):
        out = sys.stdout.buffer

        if not headers_set:
             raise AssertionError("write() before start_response()")

        elif not headers_sent:
             # Before the first output, send the stored headers
             status, response_headers = headers_sent[:] = headers_set
             out.write(wsgi_to_bytes(Status: %s\r\n % status))
             for header in response_headers:
                 out.write(wsgi_to_bytes(%s: %s\r\n % header))
             out.write(wsgi_to_bytes(\r\n))

        out.write(data)
        out.flush()

    def start_response(status, response_headers, exc_info=None):
        if exc_info:
            try:
                if headers_sent:
                    # Re-raise original exception if headers sent
                    raise exc_info[1].with_traceback(exc_info[2])
            finally:
                exc_info = None     # avoid dangling circular ref
        elif headers_set:
            raise AssertionError("Headers already set!")

        headers_set[:] = [status, response_headers]

        # Note: error checking on the headers should happen here,
        # *after* the headers are set.  That way, if an error
        # occurs, start_response can only be re-called with
        # exc_info set.

        return write

    result = application(environ, start_response)
    try:
        for data in result:
            if data:    # don‘t send headers until body appears
                write(data)
        if not headers_sent:
            write(‘‘)   # send headers now if body was empty
    finally:
        if hasattr(result, close):
            result.close()

 以上代码均出自PEP 3333官方文档

PEP 3333中对WSGI的简单示例

标签:

原文地址:http://www.cnblogs.com/chrhust/p/4299880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!